为什么在1TB稀疏文件上mmap()会失败并返回ENOMEM?

我一直在使用openSUSE 11.2 x86_64上的大型稀疏文件。 当我尝试mmap()一个1TB稀疏文件,它与ENOMEM失败。 我本以为64位地址空间足以映射成TB,但似乎不是这样。 进一步试验,1GB文件可以正常工作,但是2GB的文件(以及其他更大的文件)会失败。 我猜测可能有一个设置调整,但广泛的search没有什么变化。

下面是一些显示问题的示例代码 – 任何线索?

#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char *argv[]) { char * filename = argv[1]; int fd; off_t size = 1UL << 40; // 30 == 1GB, 40 == 1TB fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666); ftruncate(fd, size); printf("Created %ld byte sparse file\n", size); char * buffer = (char *)mmap(NULL, (size_t)size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if ( buffer == MAP_FAILED ) { perror("mmap"); exit(1); } printf("Done mmap - returned 0x0%lx\n", (unsigned long)buffer); strcpy( buffer, "cafebabe" ); printf("Wrote to start\n"); strcpy( buffer + (size - 9), "deadbeef" ); printf("Wrote to end\n"); if ( munmap(buffer, (size_t)size) < 0 ) { perror("munmap"); exit(1); } close(fd); return 0; } 

问题是每个进程的虚拟内存限制被设置为只有1.7GB。 ulimit -v 1610612736将其设置为1.5TB,我的mmap()调用成功。 谢谢, bmargulies ,提示尝试ulimit -a!

是否有某种每用户配额,限制了用户进程可用的内存量?

我的猜测是内核难以分配内存,它需要跟上这个内存映射。 我不知道如何在Linux内核中换出页面(我假定大部分文件在大部分时间都处于换出状态),但是最终可能需要每个页面的条目该文件在表中占用的内存。 由于这个文件可能被多个进程映射,所以内核必须跟踪进程的映射,映射到另一个映射到辅助存储的角度(包括设备和位置的字段)。

这将适合您的可寻址空间,但可能不适合(至少连续)在物理内存中。

如果有人知道更多关于Linux如何做,我会有兴趣听到这个。