(正确的代码在“更新5”中)
在此示例C代码中,我尝试将内存范围从0x100000000映射到0x200000000:
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <sys/mman.h> int main(void) { uint64_t* rr_addr = 0; uint64_t i = 17179869184; printf("\nsizeof(size_t): %llu\n", sizeof(size_t)); printf("(uint64_t)0x100000000: %llx\n", (uint64_t)0x100000000); printf("1L << 33: %llx\n", 1L << 33); rr_addr = mmap((void*)i, (1UL << 33), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); printf("rr_addr: %p, %llu \n", rr_addr, rr_addr); if (rr_addr == MAP_FAILED) { perror("mmap error"); } return 0; }
在不同的系统(Linux,gcc)上,我得到不同的结果:
结果1:
sizeof(size_t): 8 (uint64_t)0x100000000: 100000000 1L << 33: 200000000 rr_addr: 0xffffffffffffffff, 18446744073709551615 mmap error: Cannot allocate memory
系统信息(Fedora 14):
Linux localhost.localdomain 2.6.35.10-74.fc14.x86_64 #1 SMP Thu Dec 23 16:04:50 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4) glibc: 2.12.90-21
结果2:
sizeof(size_t): 8 (uint64_t)0x100000000: 100000000 1L << 33: 200000000 rr_addr: 0x400000000, 17179869184
系统信息(Fedora 12):
Linux wiles 2.6.32.13 #2 SMP Fri Sep 10 01:29:43 HKT 2010 x86_64 x86_64 x86_64 GNU/Linux gcc (GCC) 4.4.4 20100630 (Red Hat 4.4.4-10) glibc verison: 2.11.2-1
我期望“结果2”。也许我的代码有问题。
请帮帮我。
更新1 :如果mmap失败,则打印出errno。
更新3 :将mmap调用更改为以下行后:
char *cmd[20]; sprintf(cmd, "pmap -x %i", getpid()); printf("%s\n", cmd); system(cmd); rr_addr = mmap((void*)i, (1UL << 33), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); printf("%s\n", cmd); system(cmd);
结果:
sizeof(size_t): 8 (uint64_t)0x100000000: 100000000 1L << 33: 200000000 pmap -x 5618 5618: ./test Address Kbytes RSS Dirty Mode Mapping 0000000000400000 4 4 0 r-x-- test 0000000000600000 4 4 4 rw--- test 00007f1cc941e000 1640 280 0 r-x-- libc-2.12.90.so 00007f1cc95b8000 2044 0 0 ----- libc-2.12.90.so 00007f1cc97b7000 16 16 16 r---- libc-2.12.90.so 00007f1cc97bb000 4 4 4 rw--- libc-2.12.90.so 00007f1cc97bc000 24 16 16 rw--- [ anon ] 00007f1cc97c2000 132 108 0 r-x-- ld-2.12.90.so 00007f1cc99c6000 12 12 12 rw--- [ anon ] 00007f1cc99e0000 8 8 8 rw--- [ anon ] 00007f1cc99e2000 4 4 4 r---- ld-2.12.90.so 00007f1cc99e3000 4 4 4 rw--- ld-2.12.90.so 00007f1cc99e4000 4 4 4 rw--- [ anon ] 00007fffa0da8000 132 8 8 rw--- [ stack ] 00007fffa0dff000 4 4 0 r-x-- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------ ------ ------ total kB 4040 476 80 pmap -x 5618 5618: ./test Address Kbytes RSS Dirty Mode Mapping 0000000000400000 4 4 0 r-x-- test 0000000000600000 4 4 4 rw--- test 00007f1cc941e000 1640 280 0 r-x-- libc-2.12.90.so 00007f1cc95b8000 2044 0 0 ----- libc-2.12.90.so 00007f1cc97b7000 16 16 16 r---- libc-2.12.90.so 00007f1cc97bb000 4 4 4 rw--- libc-2.12.90.so 00007f1cc97bc000 24 16 16 rw--- [ anon ] 00007f1cc97c2000 132 108 0 r-x-- ld-2.12.90.so 00007f1cc99c6000 12 12 12 rw--- [ anon ] 00007f1cc99e0000 8 8 8 rw--- [ anon ] 00007f1cc99e2000 4 4 4 r---- ld-2.12.90.so 00007f1cc99e3000 4 4 4 rw--- ld-2.12.90.so 00007f1cc99e4000 4 4 4 rw--- [ anon ] 00007fffa0da8000 132 8 8 rw--- [ stack ] 00007fffa0dff000 4 4 0 r-x-- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------ ------ ------ total kB 4040 476 80 rr_addr: 0xffffffffffffffff, 18446744073709551615 mmap error: Cannot allocate memory
更新4 :添加“ system(” ulimit -m -v“);” 在调用mmap之前:ulimit的输出是:
max memory size (kbytes, -m) unlimited virtual memory (kbytes, -v) unlimited
除pid外,其他输出与“ Update 3”相同(仍然失败)。
更新5 :在两个系统上都可以使用的更新代码:
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <sys/mman.h> int main(void) { uint64_t* rr_addr = 0; uint64_t i = 17179869184; uint64_t len = 0; char cmd[20]; printf("\nsizeof(size_t): %llu\n", sizeof(size_t)); len = (1UL << 32); printf("len: %llx\n", len); snprintf(cmd, sizeof cmd, "pmap -x %i", getpid()); printf("%s\n", cmd); system(cmd); system("ulimit -m -v"); rr_addr = mmap((void*)i, len, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0); printf("%s\n", cmd); system(cmd); printf("rr_addr: %p, %llu \n", rr_addr, rr_addr); if (rr_addr == MAP_FAILED) { perror("mmap error"); } return 0; }
正确的答案由@caf给出:将MAP_NORESERVE标志添加到mmap可解决此问题。原因的详细信息在caf的答案中。非常感谢caf,所有这些都为您提供了有益的帮助!
如果实际上配置的交换数不超过8G,则大型映射可能会失败。
您可以添加MAP_NORESERVE标志来mmap()告诉它不要为映射预先保留任何交换空间。
MAP_NORESERVE
mmap()