Consider the following code fragment:
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
int fd = open( "/path/to/existing/file/or/device", O_RDONLY);
int numberOfWords = 4096; // chosen to be smaller than file size
int* data = mmap( NULL, nomberOfWords * sizeof(int), PROT_READ, MAP_SHARED, fd, 0);
if (data != MAP_FAILED) {
printf( "%d\n", data[0]);
// oops, forgot to munmap
close(fd);
printf( "%d\n", data[0]); // <-- why doesn't this segfault
}
背景
我正在使用一个定制的内核驱动程序,该程序使用ioctl()
设置DMA,并最终需要用户空间使用mmap()
来访问特定的缓冲区。
在编写单元测试时,我无意中发现在关闭文件描述符之前没有调用munmap
的情况下,仍然可以使用mmap'ed指针在用户空间中访问缓冲区内存。考虑到驱动程序可能存在某些错误,我编写了一个类似于此处示例的小程序来使用“正常”文件运行mmap()。
我原本期望的是,在关闭后读取会导致段错误,我的想法是当打开文件描述符的使用被关闭时,内核会自动munmap()
与文件描述符相关联的页面,就像在进程终止时发生的那样。
但实际上,我仍然能够继续使用指针。这有点令人惊讶,因为我使用mmap()
已经几年了,我肯定足够聪明(更可能是幸运)以避免暴露出这种情况的错误。在mmap
手册页中没有明显的提示。
问题
理想情况下,我们的驱动程序将需要在用户空间中引发段错误,如果发生这种情况,因为我们不希望有错误的用户空间程序写入感兴趣的内存。
那么,在不同的*nix系统中,这种行为是否相同?在给定的示例中,删除文件会导致段错误吗?或者刷新vm缓存会起作用吗?
mmap
的文档说明了在文件关闭后仍然可以继续使用内存映射区域。当映射实际消失以及每个文件描述符关闭时,你的驱动程序应该从内核核心获得通知。 - zwol