【问题标题】:How can I map a file with mmap while allocating an empty page before it?如何在文件之前分配一个空页面时使用 mmap 映射文件?
【发布时间】:2023-03-09 08:10:02
【问题描述】:

所以我需要将一个文件映射到内存中,但同时在它前面分配空间来存储一些数据。

基本上我有这个:

int fd = open(path, O_RDONLY);
if (fd < 0) {
    // error
}

struct stat file_info;
if (fstat(fd, &file_info) == -1) {
    close(fd);
    // error
}

int length = file_info.st_size;
int* data_pointer = mmap((void*) 0, length, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);

我想在内存前留出空间,可能像一页或其他东西,我可以这样做:

*data_pointer = length; // store length in space before file

// print out contents of file

const char* p = data_pointer + PAGE_SIZE;
for (int i = 0; i < *data_pointer; i++) {
    printf("%c", p[i]);
} 

printf("\n");

这样我以后可以这样做:

munmap(data_pointer, *data_pointer + PAGE_SIZE);

例如。我已经尝试使用 malloc 分配我想要的空间量,然后告诉 mmap 使用其 addr 参数映射到该空间,但我认为这不会在 100% 的时间内起作用,因为它更像是一个提示而不是命令,我担心在某些平台上,mmap 实现可能会完全忽略 addr 参数。

您是否知道任何更好的方法来完成我想要的,而不必单独跟踪每个 mmap 调用的大小(我在动态加载的库之间共享这些指针,其中一些执行 mmap 'ing,其中一些是munmap'ing,而必须处理所有这些是某种单独的列表是非常不雅的)?

现在是深夜,我真的不认为我在这里有多大意义,但无论如何,任何帮助或见解都将不胜感激。非常感谢您花时间阅读本文!

【问题讨论】:

  • 您的请求是有道理的,但我认为这不可能。您还没有真正解释要使用标头数据的用途,因此我建议您使用指向 mmap 区域的指针进行单独分配。
  • 这实际上可能正是我需要解决的问题。非常感谢您的帮助:P
  • 旁注:printf("%s\n", *(data_pointer + PAGE_SIZE)); 不是打印内存映射文件的安全方法。它里面可能有一个空字节,或者更糟糕的是,它结束后可能不会有一个空字节。
  • @JonathonReinhart 事实证明可以安全地进行(见下文)。
  • @Inobulles 我会说是的,只是因为你知道人们一直从这里复制和粘贴而不理解它或阅读 cmets,并且有一天这将导致某些安全漏洞大公司的应用程序。

标签: c memory mmap


【解决方案1】:

你在正确的轨道上。您需要的缺失部分是MAP_FIXED

int* data_pointer = mmap((void*) 0, length + PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(data_pointer == MAP_FAILED) {
    perror("mmap");
    exit(1);
}
if(mmap(data_pointer + PAGE_SIZE, length, PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, 0) == MAP_FAILED) {
    perror("mmap");
    exit(1);
}

您正确地指出,通常情况下,地址“更多的是提示而不是命令”,但传递MAP_FIXED 使其成为命令。

如果您担心安全问题,man 2 mmap 说:

MAP_FIXED 的唯一安全用途是在 addrlength 指定的地址范围之前使用另一个映射保留

这正是这种用途。

【讨论】:

  • 哦,好的。 MAP_FIXED 是否存在手册页中未提及的副作用,例如性能问题?非常感谢您的回答。
  • @Inobulles 我不知道。那里提到了我所知道的所有警告。
猜你喜欢
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 2017-09-02
  • 2023-03-06
相关资源
最近更新 更多