2010-05-26 70 views
10

我一直在使用openSUSE 11.2 x86_64上的大型稀疏文件。当我尝试mmap()1TB稀疏文件时,它与ENOMEM一起失败。我本以为64位地址空间足以映射成TB,但似乎不是。进一步试验,1GB文件可以正常工作,但2GB文件(以及其他更大的文件)会失败。我猜测可能有一个设置在某处进行调整,但广泛的搜索没有任何结果。为什么在1TB稀疏文件上mmap()会失败并显示ENOMEM?

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

#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; 
} 
+0

作为一个兴趣点,你的程序对我来说最多可以处理256GB('1 << 38')的大小,而返回EINVAL的任何数据都会更高。这是在RHEL4上(内核2.6.9-42.0.3.ELsmp)。 – caf 2010-05-26 04:39:38

+4

ulimit -a说什么? – bmargulies 2010-05-26 04:49:13

+0

谢谢,bmargulies - 就是这样。 ulimit - 报告的虚拟内存为1804800千字节(略高于1.7GB)。 ulimit -v 1610612736(1.5TB)让我mmap我的1TB稀疏文件。我会回答我自己的问题,所以我可以'关闭'它... – metadaddy 2010-05-27 05:47:39

回答

12

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

+2

而且,显然,我可以在/ etc/profile中设置所需的值(可以是'unlimited')以使其持久。 – metadaddy 2010-05-27 06:00:05

2

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

+0

是的 - 我试图尝试ulimit -a的bmargulies的建议,并指出'虚拟内存'进程限制为罪魁祸首 - 请参阅下面的答案。 .. – metadaddy 2010-05-27 05:52:24

1

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

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

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

+4

Linux将不会创建PTE(页表条目),直到实际触及这些页面。创建映射时的所有功能是创建一个单一的VMA(虚拟内存区域)结构,该结构基本上包含来自'mmap()'的信息。 – caf 2010-05-26 04:37:35

+0

@caf:感谢您的信息 – nategoose 2010-05-26 05:28:17

相关问题