c – 为什么在此示例中remap_file_pages()失败?
作者:互联网
以下C代码说明了我在Linux 2.6.30.5-43.fc11.x86_64上看到的问题:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[1024];
void *base;
int fd;
size_t pagesz = sysconf(_SC_PAGE_SIZE);
fd = open("<some file, at least 4*pagesz in length>", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
base = mmap(0, 4*pagesz, PROT_READ, MAP_SHARED, fd, 0);
if (base < 0) {
perror("mmap");
close(fd);
return 1;
}
memcpy(buf, (char*)base + 2*pagesz, 1024);
if (remap_file_pages(base, pagesz, 0, 2, 0) < 0) {
perror("remap_file_pages");
munmap(base, 4*pagesz);
close(fd);
return 1;
}
printf("%d\n", memcmp(buf, base, 1024));
munmap(base, 4*pagesz);
close(fd);
return 0;
}
这总是失败,remap_file_pages()返回-1,errno设置为EINVAL.查看内核源代码,我可以看到remap_file_pages()中的所有条件,它可能会失败,但它们似乎都不适用于我的示例.这是怎么回事?
解决方法:
它是由文件O_RDONLY打开引起的.如果将打开模式更改为O_RDWR,它就可以工作(即使mmap()仍指定PROT_READ).
do_mmap_pgoff中的此代码是根本原因 – 如果文件已打开以进行写入,它仅将vma标记为VM_SHARED:
vm_flags |= VM_SHARED | VM_MAYSHARE;
if (!(file->f_mode & FMODE_WRITE))
vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
所以在remap_file_pages()中,您在第一次检查时失败:
if (!vma || !(vma->vm_flags & VM_SHARED))
goto out;
标签:c-3,linux,mmap,memory-mapped-files 来源: https://codeday.me/bug/20190622/1259164.html