2013-07-22 38 views
7

我用一個簡單的C程序,保持分配內存試驗:失蹤[堆]在/ proc/PID/maps部分

for (i = 0; i < 10000; i ++) 
{ 
    array[i] = malloc(1024*1024); 
    if (array[i] == NULL) 
    { 
     break; 
    } 
    printf("Sleeping...%d\n", i); 
    sleep(60); 
} 

的完整代碼粘貼在這裏:http://tny.cz/2d9cb3df

然而,當我cat /proc/pid/maps,我沒有得到[heap]部分。爲什麼?

08048000-08049000 r-xp 00000000 08:11 17   /data/a.out 
08049000-0804a000 r--p 00000000 08:11 17   /data/a.out 
0804a000-0804b000 rw-p 00001000 08:11 17   /data/a.out 
0804b000-0805e000 rw-p 00000000 00:00 0 
b74c6000-b75c8000 rw-p 00000000 00:00 0 
b75c8000-b7775000 r-xp 00000000 08:01 3539272 /lib/i386-linux-gnu/libc-2.17.so 
b7775000-b7777000 r--p 001ad000 08:01 3539272 /lib/i386-linux-gnu/libc-2.17.so 
b7777000-b7778000 rw-p 001af000 08:01 3539272 /lib/i386-linux-gnu/libc-2.17.so 
b7778000-b777b000 rw-p 00000000 00:00 0 
b7797000-b779a000 rw-p 00000000 00:00 0 
b779a000-b779b000 r-xp 00000000 00:00 0   [vdso] 
b779b000-b77bb000 r-xp 00000000 08:01 3539289 /lib/i386-linux-gnu/ld-2.17.so 
b77bb000-b77bc000 r--p 0001f000 08:01 3539289 /lib/i386-linux-gnu/ld-2.17.so 
b77bc000-b77bd000 rw-p 00020000 08:01 3539289 /lib/i386-linux-gnu/ld-2.17.so 
bff21000-bff42000 rw-p 00000000 00:00 0   [stack] 
+0

的組合物1 ler推斷for循環沒有做任何事情(即,即沒有操作)並優化它? – 2013-07-22 08:04:33

+0

受過教育的猜測? –

+0

@ H2CO3,我改變它打印出分配的地址,它仍然是一樣的。 – lang2

回答

4

既然你在談論/proc/pid/maps我假設你在linux上。

這是man malloc告訴我,Linux發行版我正好運行:

通常情況下,從malloc()堆中分配內存,並調整堆所需的大小,使用sbrk(2)

當分配的內存比MMAP_THRESHOLD字節的塊,glibc的malloc()執行分配存儲器中作爲使用mmap(2)私人匿名映射。 MMAP_THRESHOLD默認爲128 kB,但可以使用mallopt(3)進行調整。

使用mmap(2)執行的分配不受RLIMIT_DATA資源限制(請參閱getrlimit(2))的影響。

如果你真的想看到你的[heap]分配/proc/pid/maps小於128k的每個呼叫對malloc。

1

上述部分只是沒有被聲明爲「堆」,因爲它是通過mmap()呼叫分配。

這裏我的64位系統上,分配的內存來自這個不斷增長部分:

7f7fbda7a000-7f7fbdc7c000 rw-p 00000000 00:00 0 
... 
7f7fbc868000-7f7fbdc7c000 rw-p 00000000 00:00 0 
... 
7f7fbc363000-7f7fbdc7c000 rw-p 00000000 00:00 0 

的部分在開始延長,總是新分配的內存IAS起始地址+ 0x10的。

什麼內存分配器在這裏所​​做的是

mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7fbb353000 

奇怪的事情;我會懷疑每個mmap() ed內存部分單獨顯示。但是,如果我有計劃做中間free()通話,內存分配如下這樣:

7f16be944000-7f16bec47000 rw-p 00000000 00:00 0 
7f16bed48000-7f16bee49000 rw-p 00000000 00:00 0 

目前已經取得了一個洞,否則連續的內存。

還有一件事發生了:在這個修改後的程序中,確實有一個[heap]部分。由於超出了我的理解reasuns,程序swithces到通過brk()分配,這是(可能),其中堆來源於:

brk()呼叫,相應的部分延伸在它的末端:

01183000-029a4000 rw-p 00000000 00:00 0         [heap] 

我不知道發生了什麼變化malloc()的心靈採取「真正的」堆(連接到brk()東西)的分配。第一個munmap()呼叫,與相應的free()有關,似乎產生了這種情況。

根據this,似乎有mmap() ed塊的最大值。如果超出這個範圍,gnulibc將回退到brk()/sbrk(),該操作在「常規堆區」上進行。

所以,短的答案:通過brk()取自malloc()版內存是「真正的」 [heap]段,mmap()版內存部分不標記爲[heap]

0

動態分配是通過使用brk()調用進行的。 .brk部分的開始在程序加載期間計算(查看/linux/fs/binfmt_elf.c中的load_elf_binary())。但是,只有在請求實際分配的運行時纔會映射頁面。請參見下面的/ proc /進程/地圖的屏幕顯示之前和之後的x86_64系統上

上的分配調用釋放calloc(8032,1)之前:

$ cat /proc/$(pid)/maps 

00400000-00401000 r-xp 00000000 08:02 1314308    /testheap 

00600000-00601000 r--p 00000000 08:02 1314308    /testheap 

00601000-00602000 rw-p 00001000 08:02 1314308    /testheap 

7fafeea3e000-7fafeebfb000 r-xp 00000000 08:02 198420  /lib/x86_64-linux-gnu/libc-2.17.so 

7fafeebfb000-7fafeedfb000 ---p 001bd000 08:02 198420  /lib/x86_64-linux-gnu/libc-2.17.so 

後調用釋放calloc(8032,1):

$cat /proc/$(pid)/maps 

00400000-00401000 r-xp 00000000 08:02 1314308    /testheap 

00600000-00601000 r--p 00000000 08:02 1314308    /testheap 

00601000-00602000 rw-p 00001000 08:02 1314308    /testheap 

**021ea000-0220c000 rw-p 00000000 00:00 0     [heap]** 

7fafeea3e000-7fafeebfb000 r-xp 00000000 08:02 198420  /lib/x86_64-linux-gnu/libc-2.17.so 

7fafeebfb000-7fafeedfb000 ---p 001bd000 08:02 198420  /lib/x86_64-linux-gnu/libc-2.17.so