malloc記憶體分配原理

2021-09-02 20:25:01 字數 2216 閱讀 9028

一、malloc的工作機制

它有乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶

呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給使用者的那塊記憶體傳給使用者,並將剩下的那塊(如果有的話)返回到連線表上。

呼叫free函式時,它將使用者釋放的記憶體塊連線到空閒鏈上。到最後,空閒鏈會被切成很多的小記憶體片段,如果這時使用者申請乙個大的記憶體片段,那麼空閒鏈上可能沒有可以滿足使用者要求的片段了。於是,malloc函式請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各記憶體片段,對它們進行整理,將相鄰的小空閒塊合併成較大的記憶體塊

glibc維護了不止乙個不定長的記憶體塊鍊錶,而是好幾個,每乙個這種鍊錶負責乙個大小範圍,這種做法有效減少了分配大記憶體時的遍歷開銷

glibc另外的策略就是不止維護一類空閒鍊錶,而是另外再維護乙個緩衝鍊錶乙個高速緩衝鍊錶

在分配的時候首先在快取記憶體中查詢,失敗之後再在空閒鍊錶查詢,如果找到的記憶體塊比較大,那麼將切割之後的剩餘記憶體塊插入到快取鍊錶。

如果空閒鍊錶查詢失敗那麼就往快取鍊錶中查詢. 如果還是沒有合適的空閒塊,就向記憶體申請比請求數更大的記憶體塊,然後把剩下的記憶體放入鍊錶中。

在對記憶體塊進行了 free 呼叫之後,我們需要做的是諸如將它們標記為未被使用的等事情,並且,在呼叫 malloc 時,我們要能夠定位未被使用的記憶體塊。因此, malloc返回的每塊記憶體的起始處首先要有這個結構:

struct mem_control_block ;
這就解釋了,為什麼在程式中free之後,但是堆的記憶體還是沒有釋放。

二、sbrk & brk

malloc所申請的記憶體主要從heap區域分配(本文不考慮通過mmap申請大塊記憶體的情況)。

程序所面對的虛擬記憶體位址空間,只有按頁對映到物理記憶體位址,才能真正使用。受物理儲存容量限制,整個堆虛擬記憶體空間不可能全部對映到實際的物理記憶體。linux對堆的管理示意如下:

linux維護乙個break指標,這個指標指向堆空間的某個位址。從堆起始位址到break之間的位址空間為對映好的,可以供程序訪問;而從break往上,是未對映的位址空間,如果訪問這段空間則程式會報錯。

由上文知道,要增加乙個程序實際的可用堆大小,就需要將break指標向高位址移動linux通過brk和sbrk系統呼叫操作break指標。兩個系統呼叫的原型如下:

int brk(void *addr);

void *sbrk(intptr_t increment);

brk將break指標直接設定為某個位址,而sbrk將break從當前位置移動increment所指定的增量。brk在執行成功時返回0,否則返回-1並設定errno為enomem;sbrk成功時返回break移動之前所指向的位址,否則返回(void *)-1。

乙個小技巧是,如果將increment設定為0,則可以獲得當前break的位址。

另外需要注意的是,由於linux是按頁進行記憶體對映的,所以如果break被設定為沒有按頁大小對齊,則系統實際上會在最後對映乙個完整的頁,從而實際已對映的記憶體空間比break指向的地方要大一些。但是使用break之後的位址是很危險的(儘管也許break之後確實有一小塊可用記憶體位址)。

注意大部份unix虛擬記憶體的使用是只增不減的。

code:malloc(32 * 1024) --->;sbrk += 32 * 1024

free() --->;sbrk 不減少。

但如如果再來一次

malloc(32 * 1024) ---->;sbrk 也不增,使用原有空間.

但對於linux來說它是要以記憶體的最大數收縮的;

code:a = malloc(32 * 1024) -->;sbrk += 32 * 1024

b = malloc(32 * 1024) -->;sbrk += 32 * 1024

if(****)

else

malloc記憶體分配原理

一 malloc的工作機制 它有乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶。呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二 一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組 接下來,將分配給使用者的那塊記憶體傳給...

記憶體分配 malloc 和free

一些關於關於記憶體分配 malloc 和free 的基本知識。有關指標 指標是用來存放記憶體位址的,分型別的原因是,指標變數儲存的是乙個記憶體空間的首位址 第乙個位元組的位址 但這個空間占用的位元組和存放的數的型別,是由指標的型別來表明的。系統根據指標型別取相應連續的記憶體作為乙個資料。儲存型別和動...

記憶體分配(malloc 和free )

c語言的乙個特性是接近底層,對於硬體的控制能力比其他高階動態語言要強。同時,c語言賦予程式設計師更大的自由度,更信任程式設計師。在記憶體的分配與釋放上,我們知道非靜態變數 塊作用域,無鏈結,自動生存期 在程式進入到變數定義所在的地方 塊或函式內 時分配記憶體,在離開塊作用域時釋放。對於靜態變數,在程...