当长度大于4GB时,mmap失败

eri*_*zma 13 c linux gcc glibc fedora

(正确的代码在'Update 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;
}
Run Code Online (Sandbox Code Playgroud)

在不同的系统(Linux,gcc)上,我得到了不同的结果:

结果1:

sizeof(size_t): 8
(uint64_t)0x100000000: 100000000
1L << 33: 200000000
rr_addr: 0xffffffffffffffff, 18446744073709551615 
mmap error: Cannot allocate memory
Run Code Online (Sandbox Code Playgroud)

系统信息(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
Run Code Online (Sandbox Code Playgroud)

结果2:

sizeof(size_t): 8
(uint64_t)0x100000000: 100000000
1L << 33: 200000000
rr_addr: 0x400000000, 17179869184 
Run Code Online (Sandbox Code Playgroud)

系统信息(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
Run Code Online (Sandbox Code Playgroud)

我期待"结果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);
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)

更新4:添加"system("ulimit -m -v");" 在调用mmap之前:ulimit的输出是:

max memory size         (kbytes, -m) unlimited
virtual memory          (kbytes, -v) unlimited
Run Code Online (Sandbox Code Playgroud)

除了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;
}
Run Code Online (Sandbox Code Playgroud)

正确的答案由@caf给出:向mmap添加MAP_NORESERVE标志解决了这个问题.详细的原因在于caf的回答.非常感谢咖啡馆,所有这些都给予了一些帮助!

caf*_*caf 8

如果您实际上没有配置超过8G的交换,那么该大型映射可能会失败.

您可以添加MAP_NORESERVE标志以mmap()告诉它不要为前映射保留任何交换空间.