请考虑以下代码片段:
#include#include #include #include 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指针访问用户空间中的缓冲区内存.想到驱动程序中有一些错误我编写了一个类似于此处所示的小程序,用一个"普通"文件来运行mmap().
我期待看到的是关闭后读取的段错误,我的想法是,munmap()
当打开文件描述符的使用被关闭时,内核将自动与文件描述符关联的页面,类似于进程时的情况被终止.
相反,我能够继续使用指针.这有点令人惊讶,因为我已经使用mmap()
了几年,我一定很聪明(更可能是幸运的)足以避免可能暴露这种情况的错误.mmap
手册页中没有任何内容.
理想情况下,如果发生这种情况,我们的驱动程序将需要在用户空间中导致段错误,因为我们不希望有错误的用户空间程序写入感兴趣的内存.
那么,这种行为在不同的*nix中是否相同?在给定的示例中,是否需要删除文件以导致段错误?或者也许刷新vm缓存?
好吧,在写完大部分问题之后,我发现这个不同的问题与我的搜索方式不同:在调用mmap之后我是否需要保持文件打开?
答案引用了POSIX手册,结果在man页面中(munmap
在传递下, - |),解释说关闭描述符不会自动取消映射映射.所以看起来我们需要修改我们的驱动程序关闭代码以使相关的内存映射无效,以便在用户空间中发生段错误.
我决定发布这个问题以防其他人搜索类似的东西.