2012-02-20 41 views
4

malloc函數同時使用sbrkmmap函數。現在sbrk函數增加或減少數據段。所以它線性增長。現在我的問題是,這種線性是否始終保持不變,或者例如,mmap調用可以分配與數據段重疊的內存?通過mmap分配的內存是否與數據段重疊

我正在討論在多核系統上運行的多線程程序。關於sbrk用於多線程程序存在一些嚴重缺陷This blog會談,並指出,這可能是與sbrk分配的內存可以存儲與mmapalloacted間雜的sbrk堆可能變得不連續,因爲mmaped區域或共享對象學障礙堆的增長)。

+0

只是要清楚,當你說*線性*,你的意思是*連續性*? – NPE 2012-02-20 18:35:11

+0

是的線性我的意思是連續性。 – MetallicPriest 2012-02-20 18:36:41

回答

11

該博客文章沒有看到樹木的森林;只允許malloc實現以非零參數調用sbrk。更確切地說,如果應用程序代碼調用sbrk非零參數,則Unix的大多數malloc實現將停止正常運行(並且我的意思是「您的程序將崩潰」)。如果你想直接從操作系統做出大量分配,你必須必須使用mmap來做到這一點。

(這是事實,在多線程程序,malloc必須在內部環繞其呼叫互斥sbrk,但是這是一個實現細節。POSIX說malloc是線程安全的,這是一個應用程序的程序員最重要的事情。 )

mmap不會分配內存除非你使用MAP_FIXED重疊brk區域。如果你使用MAP_FIXED並且你的程序爆炸了,你可以保留所有的部分。

內核試圖避免這樣做,但在正常操作中的mmap可能會分配內存接近brk區域的頂部。如果發生這種情況,隨後的sbrk呼叫將與mmap區域發生衝突,將失敗。它會而不是分配不連續的內存。 malloc的好實現應該檢測到這種情況,並開始使用mmap的一切。我沒有真正嘗試過,但測試程序很容易編寫。

+0

非常好的答案。它清除了我腦海中的混亂。謝謝。 – MetallicPriest 2012-02-20 18:54:31

+1

還要注意,你不知道在實現中調用'malloc'中的哪些函數(例如,在glibc中,甚至是'snprintf'和'dprintf'在內部調用'malloc'來處理格式字符串),所以我會盡可能說除非你的程序只使用異步信號安全函數,否則用非零參數調用'sbrk'是非常不安全的。 – 2012-02-20 19:06:25

3

是這種線性始終保持,或者例如,一個mmap調用可以分配與數據段重疊的內存?

觀察到的行爲是brk區域總是線性的。實現細節:如果擴大brk區域是不可能的,例如由於阻塞映射,glibc將切換到mmap-only。小分配(< 128KB)似乎是由glibc的通過BRK如果有可能獲得,所以阻斷有:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/mman.h> 

int main(void) 
{ 
     int i; 
     for (i = 0; i < 1024; ++i) { 
       malloc(2048); 
       if (i == 512) { 
         void *r, *end = sbrk(0); 
         r = mmap(end, 4096, PROT_NONE, 
          MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 
       } 
     } 
} 

straced時,收益率確實

[...] 
brk(0x1e7d000)       = 0x1e7d000 
mmap(0x1e7d000, 4096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x1e7d000 
brk(0x1e9e000)       = 0x1e7d000 <-- (!) 
mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbfd9bc9000