如何在分配空白页之前使用 mmap 映射文件?

How can I map a file with mmap while allocating an empty page before it?

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

基本上我有这个:

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);

并且我希望在内存前面有 space,可能是一页之类的,我可以在其中执行此操作:

*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 分配我想要的 space 的数量,然后告诉 mmap 使用它的 addr 参数映射到那个 space,但是我不要认为这在 100% 的时间都有效,因为它更多的是提示而不是命令,而且我担心在某些平台上,mmap 实现可能会完全忽略 addr 参数.

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

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

你走在正确的轨道上。您需要的缺失部分是 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);
}

您正确地指出,通常地址是 "more of a hint than an order",但传递 MAP_FIXED 使其成为订单。

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

The only safe use for MAP_FIXED is where the address range specified by addr and length was previously reserved using another mapping

这就是这个用途。