|
free() 函數(shù)只傳入一個(gè)內(nèi)存地址,為什么能知道要釋放多大的內(nèi)存?
free()函數(shù),要求傳入的參數(shù)必須是malloc的返回值。在進(jìn)行malloc函數(shù)申請(qǐng)內(nèi)存時(shí),操作系統(tǒng)實(shí)際會(huì)申請(qǐng)大于malloc要求的長(zhǎng)度。
malloc分配的內(nèi)存為一個(gè)個(gè)chunk,以下是一個(gè)典型的 malloc_chunk 結(jié)構(gòu)定義(以 glibc 為例):
struct malloc_chunk { size_t prev_size; /* 前一個(gè)內(nèi)存塊的大。ㄈ绻喜⒌脑挘 */ size_t size; /* 當(dāng)前內(nèi)存塊的大小,包括邊界標(biāo)記 */ struct malloc_chunk *fd; /* 指向前一個(gè)空閑內(nèi)存塊的指針(用于空閑內(nèi)存列表) */ struct malloc_chunk *bk; /* 指向下一個(gè)空閑內(nèi)存塊的指針(用于空閑內(nèi)存列表) */};prev_size 字段表示前一個(gè)內(nèi)存塊的大。ㄈ绻(dāng)前內(nèi)存塊與前面的內(nèi)存塊合并在一起)。size 字段表示當(dāng)前內(nèi)存塊的大小,包括邊界標(biāo)記。fd 和 bk 字段分別表示指向前后空閑內(nèi)存塊的指針,用于維護(hù)空閑內(nèi)存列表。
當(dāng)釋放一個(gè)內(nèi)存塊時(shí),內(nèi)存分配器可以檢查 prev_size 字段以確定前一個(gè)內(nèi)存塊是否為空閑。如果前一個(gè)內(nèi)存塊為空閑,內(nèi)存分配器可以將這兩個(gè)相鄰的空閑內(nèi)存塊合并成一個(gè)更大的空閑內(nèi)存塊。這樣可以使內(nèi)存分配更加高效,減少內(nèi)存碎片
圖解chunk內(nèi)存塊:
oawfmead45y6405148308.png (22.1 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
oawfmead45y6405148308.png
昨天 07:37 上傳
malloc返回的指針不是指向了Header,而是指向了Payload開(kāi)始處。
所以空間的大小記錄在參數(shù)指針指向地址的前面,free的時(shí)候通過(guò)這個(gè)記錄即可知道要釋放的內(nèi)存有多大。
31nqxcbvzfs6405148408.png (59.02 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
31nqxcbvzfs6405148408.png
昨天 07:37 上傳
不同的內(nèi)存分配器實(shí)現(xiàn)不一樣,glibc的ptmalloc采用的是這種隱藏頭風(fēng)格,gemalloc采用其他的實(shí)現(xiàn)方式。
關(guān)于malloc還有幾個(gè)知識(shí)點(diǎn):
malloc是系統(tǒng)調(diào)用嗎?
malloc是C語(yǔ)言庫(kù)函數(shù)不是系統(tǒng)函數(shù)調(diào)用。
malloc 申請(qǐng)內(nèi)存的時(shí)候,會(huì)有兩種方式向操作系統(tǒng)申請(qǐng)堆內(nèi)存。
方式一:通過(guò) brk() 系統(tǒng)調(diào)用從堆分配內(nèi)存
方式二:通過(guò) mmap() 系統(tǒng)調(diào)用在文件映射區(qū)域分配內(nèi)存;
i1h3yao54k46405148508.jpg (131.18 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
i1h3yao54k46405148508.jpg
昨天 07:37 上傳
mafbrkqn5uh6405148608.jpg (130.32 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
mafbrkqn5uh6405148608.jpg
昨天 07:37 上傳
malloc分配的是物理內(nèi)存嗎?
答案:不是物理內(nèi)存,是虛擬內(nèi)存。
現(xiàn)在的操作系統(tǒng),內(nèi)存管理通常是基于虛擬內(nèi)存的,所以應(yīng)用程序看到的內(nèi)存地址(虛擬地址)與實(shí)際的物理內(nèi)存地址(物理地址)是不同的。操作系統(tǒng)通過(guò)內(nèi)存管理單元(MMU)來(lái)將虛擬地址轉(zhuǎn)換為物理地址。
當(dāng)應(yīng)用程序首次訪問(wèn)這塊內(nèi)存時(shí),操作系統(tǒng)發(fā)現(xiàn)對(duì)應(yīng)的物理內(nèi)存尚未分配,它會(huì)從可用的物理內(nèi)存中分配相應(yīng)的空間,并更新頁(yè)表項(xiàng)以完成虛擬地址到物理地址的映射。
如果這塊內(nèi)存從來(lái)沒(méi)有被訪問(wèn),那么就不會(huì)分配實(shí)際的物理內(nèi)存,節(jié)約了內(nèi)存。
調(diào)用free后,內(nèi)存會(huì)被操作系統(tǒng)立馬回收嗎?
答案:不會(huì)。
當(dāng)程序員使用free函數(shù)釋放內(nèi)存后,?這塊內(nèi)存并不會(huì)立即被歸還給操作系統(tǒng)。?相反,?這些被釋放的內(nèi)存首先會(huì)被內(nèi)存管理器(?如ptmalloc)?保存起來(lái),?以便后續(xù)重用。?這樣做的主要目的是減少與操作系統(tǒng)的內(nèi)存交互次數(shù),?從而降低系統(tǒng)調(diào)用的開(kāi)銷。
?
內(nèi)存管理器會(huì)使用雙鏈表等方式來(lái)管理這些被釋放的內(nèi)存塊,?當(dāng)程序再次申請(qǐng)內(nèi)存時(shí),?內(nèi)存管理器會(huì)首先嘗試從這些已釋放的內(nèi)存塊中找到合適的塊返回給程序,?而不是直接向操作系統(tǒng)請(qǐng)求新的內(nèi)存。?這種機(jī)制有助于減少內(nèi)存碎片和提高內(nèi)存使用效率。
end
一口Linux
關(guān)注,回復(fù)【1024】海量Linux資料贈(zèng)送
精彩文章合集
文章推薦
?【專輯】ARM?【專輯】粉絲問(wèn)答?【專輯】所有原創(chuàng)?【專輯】linux入門?【專輯】計(jì)算機(jī)網(wǎng)絡(luò)?【專輯】Linux驅(qū)動(dòng)?【干貨】嵌入式驅(qū)動(dòng)工程師學(xué)習(xí)路線?【干貨】Linux嵌入式所有知識(shí)點(diǎn)-思維導(dǎo)圖 |
|