malloc 底層實現及原理


摘要:偶爾看到面試題會問到 malloc 的底層原理,今天就來記錄一下,畢竟學習要“知其所以然”,這樣才會胸有成竹。

注:下面分析均是基於 linux 環境下的 malloc 實現。步驟是:先總結結論,再逐步展開

結論

1)當開辟的空間小於 128K 時,調用 brk()函數,malloc 的底層實現是系統調用函數 brk(),其主要移動指針 _enddata(此時的 _enddata 指的是 Linux 地址空間中堆段的末尾地址,不是數據段的末尾地址)

2)當開辟的空間大於 128K 時,mmap()系統調用函數來在虛擬地址空間中(堆和棧中間,稱為“文件映射區域”的地方)找一塊空間來開辟。

具體內容

當一個進程發生缺頁中斷的時候,進程會陷入核心態,執行以下操作:

1)檢查要訪問的虛擬地址是否合法

2)查找/分配一個物理頁

3)填充物理頁內容(讀取磁盤,或者直接置0,或者什么都不做)

4)建立映射關系(虛擬地址到物理地址的映射關系)

5)重復執行發生缺頁中斷的那條指令

如果第3布,需要讀取磁盤,那么這次缺頁就是 majfit(major fault:大錯誤),否則就是 minflt(minor fault:小錯誤)

內存分配的原理

從操作系統角度看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk 和 mmap (不考慮共享內存)

1)brk 是將數據段(.data)的最高地址指針 _edata 往高地址推

2)mmap 是在進程的虛擬地址空間中(堆和棧中間,稱為“文件映射區域”的地方)找一塊空閑的虛擬內存。

這兩種方式分配的都是虛擬內存,沒有分配物理內存。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操作系統負責分配物理內存,然后建立虛擬內存和物理內存之間的映射關系。

具體分配過程

情況一:malloc 小於 128K 的內存,使用 brk 分配

將_edata往高地址推(只分配虛擬空間,不對應物理內存(因此沒有初始化),第一次讀/寫數據時,引起內核缺頁中斷,內核才分配對應的物理內存,然后虛擬地址空間建立映射關系),如下圖:

1,進程啟動的時候,其(虛擬)內存空間的初始布局如圖1所示

2,進程調用A=malloc(30K)以后,內存空間如圖2:

  malloc函數會調用brk系統調用,將_edata指針往高地址推30K,就完成虛擬內存分配

  你可能會問:難道這樣就完成內存分配了?

  事實是:_edata+30K只是完成虛擬地址的分配,A這塊內存現在還是沒有物理頁與之對應的,等到進程第一次讀寫A這塊內存的時候,發生缺頁中斷,這個時候,內核才分配A這塊內存對應的物理頁。也就是說,如果用malloc分配了A這塊內容,然后從來不訪問它,那么,A對應的物理頁是不會被分配的。

3,進程調用B=malloc(40K)以后,內存空間如圖3

情況二:malloc 大於 128K 的內存,使用 mmap 分配(munmap 釋放)

4,進程調用C=malloc(200K)以后,內存空間如圖4

  默認情況下,malloc函數分配內存,如果請求內存大於128K(可由M_MMAP_THRESHOLD選項調節),那就不是去推_edata指針了,而是利用mmap系統調用,從堆和棧的中間分配一塊虛擬內存

這樣子做主要是因為:

  brk分配的內存需要等到高地址內存釋放以后才能釋放(例如,在B釋放之前,A是不可能釋放的,因為只有一個_edata 指針,這就是內存碎片產生的原因,什么時候緊縮看下面),而mmap分配的內存可以單獨釋放。

當然,還有其它的好處,也有壞處,再具體下去,有興趣的同學可以去看glibc里面malloc的代碼了。

 5,進程調用D=malloc(100K)以后,內存空間如圖5

 6,進程調用free(C)以后,C對應的虛擬內存和物理內存一起釋放

7,進程調用free(B)以后,如圖7所示

  B對應的虛擬內存和物理內存都沒有釋放,因為只有一個_edata指針,如果往回推,那么D這塊內存怎么辦呢當然,B這塊內存,是可以重用的,如果這個時候再來一個40K的請求,那么malloc很可能就把B這塊內存返回回去了

8,進程調用free(D)以后,如圖8所示

  B和D連接起來,變成一塊140K的空閑內存  

9,默認情況下:

  當最高地址空間的空閑內存超過128K(可由M_TRIM_THRESHOLD選項調節)時,執行內存緊縮操作(trim)。在上一個步驟free的時候,發現最高地址空閑內存超過128K,於是內存緊縮,變成圖9所示

 

參考博客:https://www.cnblogs.com/dongzhiquan/p/5621906.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM