我有一个小示例程序,只需fopen
个文件并使用fgets
来读取它。使用strace
,我注意到第一次调用fgets
运行mmap
系统调用,然后读取系统调用用于实际读取文件的内容。在fclose
上,文件为munmap
。如果我改为打开直接读取文件,这显然不会发生。我很好奇这个mmap
的目的是什么,以及它正在实现什么。
在我的基于Linux 2.6.31的系统上,当虚拟内存需求很大时,这些mmap
有时会挂起几秒钟,在我看来是不必要的。
示例代码:
#include <stdlib.h>
#include <stdio.h>
int main ()
{
FILE *f;
if ( NULL == ( f=fopen( "foo.txt","r" )))
{
printf ("Fail to open\n");
}
char buf[256];
fgets(buf,256,f);
fclose(f);
}
以上是运行上述代码时的相关strace输出:
open("foo.txt", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=9, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8039000
read(3, "foo\nbar\n\n"..., 4096) = 9
close(3) = 0
munmap(0xb8039000, 4096) = 0
答案 0 :(得分:15)
这不是mmap
编辑的文件 - 在这种情况下,mmap
是匿名使用的(不是在文件上),可能是为后续读取将使用的缓冲区分配内存。 / p>
malloc
实际上导致对mmap
的调用。同样,munmap
对应于对free
的调用。
答案 1 :(得分:5)
mmap
未映射文件;相反,它为stdio FILE
缓冲分配内存。通常malloc
不会使用mmap
来为这么小的分配服务,但似乎glibc的stdio实现直接使用mmap
来获取缓冲区。这可能是为了确保页面对齐(尽管posix_memalign
可以实现相同的目的)和/或确保关闭文件将缓冲区内存返回给内核。我质疑页面对齐缓冲区的用处。大概这是为了性能,但我看不出它会有什么帮助,除非你读取的文件偏移也是页面对齐的,即便如此,它似乎是一个可疑的微优化。
答案 2 :(得分:1)
从我读过的内存映射函数在处理大文件时很有用。现在大的定义是我不知道的。但是对于大文件来说,与“缓冲”的i / o调用相比,它们明显更快。
在您发布的示例中,我认为文件是由open()
函数打开的,而mmap用于分配内存或其他内容。
从mmap函数的语法中可以清楚地看到:
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
第二个参数采用非负的文件描述符。
在堆栈跟踪中,它是-1
答案 3 :(得分:0)
glibc中fopen的源码显示mmap是可以实际使用的。