1. 程式人生 > >ptmalloc一些細節流程

ptmalloc一些細節流程

保存 lai sorted top none 如果 global 釋放 -c

  • chunk 容器
  1. Bins
    • ptmalloc統一管理heap和mmap區的chunk,避免了頻繁的系統調用,一共維護了128個bin,使用數組來存儲,所有的bin都是雙向鏈表。

技術分享圖片

  2.Fast Bins

    • 對於不大於max_fast的chunk加入fast bins,標誌位P不改變(為了不使其合並),在認為內存碎片太多時會將其合並加入unsorted bin。

  3.Unsorted Bin

    • 對於回收的chunk大於max_fast或合並完的 fast bin 會加在這裏,在fast bin中沒有找到合適的chunk後,會在這裏找,如果沒有將其加入到合適的bin中,相當於其他bin的高速緩存。

  4.Top chunk

    • 在sub_heap的最高處不屬於任何chunk,總是在small bin 和large bin 後考慮,與收縮條件息息相關。

  5.mmap chunk

    • 申請的內存足夠大時,直接使用mmap向系統申請資源,同時釋放時也是直接解除映射。

  6.Last remainder

    • 一種特殊的chunk,不屬於任何bin,當需要分配一個small chunk時,沒有相應的chunk,last remainder chunk會分裂成兩個,一個返回給用戶,另一個變成新的last remainder chunk。
  • 核心結構
  1. 對於主分配區,使用了靜態全局的結構體定義(malloc_par),保證只有一份。
  2. 對於非主分配區,由多個sub_heap組成。第一個sub_heap中,最頂端是heap_info,接下來是malloc_state的實例(保存了分配去相應的信息),接下來是chunk。heap_info中利用單鏈表將sub_heap連接起來,後續的sub_heap由heap_info和chunk構成。
  • 初始化
  1. 分配區的初始化:首先遍歷所有的bins,修改指針指向,設置了全局變量global_max_fast,在主分配區初始化時賦值,最後初始化top_chunk。
  2. ptmalloc初始化:
    • 調用malloc前定義了hooks函數,對ptmalloc進行初始化,對於多線程的ptmalloc,同時需要調用pthread_initilaize初始化pthread。
    • 定義了判斷是否初始化過的全局變量_malloc_initalized(值為1時說明初始化完成)。
    • 初始化全局鎖list_lock用於同步分配區的單向循環鏈表,創建線程私有實例arena_key只想主分配區,以後每次分配內存後調整arena_key使不總在一個分配區分配資源。
    • 初始化fork子進程時調用的回調函數:在本線程fork子進程時,調用ptmalloc_lock_all()獲得所有分配區的鎖,當子進程創建完畢時,父進程調用ptmalloc_unlock_all()重新unlock每個分配區的鎖,子進程調用ptmallic_unlock_all2()重新初始化每個分配區的鎖。對於從父進程繼承的鎖不安全會造成內存泄漏,所以需要重新初始化。另外對於遞歸fork子進程時,使用了atfork_recursive_cntr引用計數,方便父進程正確解鎖。
  • 獲取分配區:(PER_THREAD開啟)首先嘗試從分配區的free_list中獲得一個分配區(由父進程繼承而來),如果沒有則嘗試重用分配區,如果仍然沒有則創建新的分配區。
  • 當_int_malloc()函數嘗試從fast bins,last remainder chunk,small bins,large bins和top chunk都失敗都就會使用sysMalloc()函數直接向系統申請內存用於分配所需的chunk。

ptmalloc一些細節流程