只读映射超大文件时mmap调用报ENOMEM错误,求解决方法
问题:240GiB只读文件mmap失败(Errno=9)
复现代码
#include <stdio.h> #include <sys/mman.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> void main() { int fd = open("file.data", O_RDONLY); void* ptr = mmap(0, (size_t)240 * 1024 * 1024 * 1024, PROT_READ, MAP_SHARED, fd, 0); printf("Result = %p\n", ptr); printf("Errno = %d\n", errno); }
编译运行命令
gcc test.c && ./a.out
运行输出
Result = 0xffffffffffffffff Errno = 9
目标文件信息
file.data是一个243 GiB的文件,其stat信息如下:
$ stat file.data File: file.data Size: 260165023654 Blocks: 508135088 IO Block: 4096 regular file Device: 801h/2049d Inode: 6815790 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1001/ user) Gid: ( 1001/ user) Access: 2023-05-08 09:22:07.314477587 -0400 Modify: 2023-06-16 07:53:12.275187040 -0400 Change: 2023-06-16 07:53:12.275187040 -0400 Birth: -
系统配置及参数
系统为Debian Stretch、Linux 5.2.21,相关参数如下:
内存超额配置设置
$ sysctl vm.overcommit_memory vm.overcommit_memory = 1
资源限制
$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 768178 max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 768178 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
内存状态
$ free -m total used free shared buff/cache available Mem: 192105 671 189213 9 2220 190314 Swap: 0 0 0
已尝试的优化措施
- 未使用
MAP_PRIVATE+PROT_WRITE的映射组合 - 已将
ulimit -v设为unlimited - 已设置
vm.overcommit_memory=1
疑问与诉求
按道理这个只读mmap应该能成功:内核可以随时将映射页换出到磁盘,而且64位系统应该有足够的连续虚拟地址空间。请问如何让mmap调用成功?
程序的/proc/*/maps输出
2aaaaaa000-2aaaaab000 r-xp 00000000 08:01 6815754 /home/<username>/a.out 2aaacaa000-2aaacab000 r--p 00000000 08:01 6815754 /home/<username>/a.out 2aaacab000-2aaacac000 rw-p 00001000 08:01 6815754 /home/<username>/a.out 3ff7a3a000-3ff7bcf000 r-xp 00000000 08:01 5767499 /lib/x86_64-linux-gnu/libc-2.24.so 3ff7bcf000-3ff7dcf000 ---p 00195000 08:01 5767499 /lib/x86_64-linux-gnu/libc-2.24.so 3ff7dcf000-3ff7dd3000 r--p 00195000 08:01 5767499 /lib/x86_64-linux-gnu/libc-2.24.so 3ff7dd3000-3ff7dd5000 rw-p 00199000 08:01 5767499 /lib/x86_64-linux-gnu/libc-2.24.so 3ff7dd5000-3ff7dd9000 rw-p 00000000 00:00 0 3ff7dd9000-3ff7dfc000 r-xp 00000000 08:01 5767249 /lib/x86_64-linux-gnu/ld-2.24.so 3ff7fe8000-3ff7fea000 rw-p 00000000 00:00 0 3ff7ff8000-3ff7ffb000 r--p 00000000 00:00 0 [vvar] 3ff7ffb000-3ff7ffc000 r-xp 00000000 00:00 0 [vdso] 3ff7ffc000-3ff7ffd000 r--p 00023000 08:01 5767249 /lib/x86_64-linux-gnu/ld-2.24.so 3ff7ffd000-3ff7ffe000 rw-p 00024000 08:01 5767249 /lib/x86_64-linux-gnu/ld-2.24.so 3ff7ffe000-3ff7fff000 rw-p 00000000 00:00 0 3ffffde000-3ffffff000 rw-p 00000000 00:00 0 [stack] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
内容的提问来源于stack exchange,提问作者cmpxchg8b
相关产品推荐
相关产品推荐

