堆基礎 2 開始入微資料結構

2021-09-27 03:07:27 字數 3604 閱讀 2187

有三個極其重要的堆資料結構是用於堆的管理

乙個典型的main_arena和thread_arena的示意圖如下

對於乙個執行緒的arena,可能存在多個heap段 示意圖如下,可以看出乙個arena通過heap_info資料結構中相關的指標作為鍊錶串接在一起 當然對於其他派生的heap,則沒有malloc_state的結構,其頂部仍然是top chunk的資料結構

下面開始就要仔細分析chunk的型別了

chunk的型別有以下四種

chunk的資料結構表達如下

struct malloc_chunk 

;

處於使用狀態的chunk結構如下 即allocated chunk的資料結構如下 由以下幾種成分構成

值得一提的是 allocated chunk的下乙個chunk的malloc_chunk資料結構的prev_size欄位是作為user_data的一部分來使用 因為prev_size是針對於free chunk設定的 即記錄的是free chunk的大小

free chunk的結構圖如下所示 成分如下

bins是用來串連free塊的乙個list鍊錶 用來管理free chunk的鍊錶 基於chunk_size 有不同的bins 主要有以下四種型別的bins

用來儲存這些bins的資料結構有以下兩種

fastbins的示意圖如下

當small chunk或者large chunk被釋放後 , 並不會將他們直接放入獨自該去的bin中 而是將他們新增到unsorted bin上。 之所以這樣是因為glibc可以最大限度的使用最近使用過的chunk。這將相當於unsorted bin是乙個針對於small bins 和 large bins的乙個高速緩衝 unsorted bin鍊錶是乙個雙向的迴圈鍊錶

bins的結構圖如下所示

large bin 中收納的是大於等於512bytes的chunk塊。large bin在bins中的範圍是64-126 64正好是26 這樣設計也是為了方便查詢index設計的吧。large bins中的每個bin也是乙個雙向迴圈鍊錶!!!largebins中的bin數量是63個

正是因為每個large bin中存放的chunk size是乙個浮動的值 所以需要進行降序排序,即大chunk塊放入煉表頭 之後的chunk_size依次遞減兩個free的塊也是無法相鄰的,所以會被整合後統一先放入到unsorted bin中當使用者呼叫malloc申請large chunk的時候 ,第一次由於所有的large bins都為null 所以此時服務該malloc的**是** next largest bin code** 在第一次呼叫malloc的時候 此時small bins和large bins會被初始化 即fd和bk指標指向本身所屬的bin結點。當之後large bins不為空之後首先判別在對應index的large bin中是否存在著大於使用者申請的chunk塊 若存在最大尺寸的塊大於使用者申請的尺寸 則從末段 即最小尺寸的chunk開始向後遍歷 找到第乙個大於等於使用者申請尺寸的chunk 然後這個塊肯定不會直接返還給使用者 因為直接給有可能造成浪費情況 所以這個chunk會被split成兩個塊乙個自然是使用者所需要的user chunk 這個chunk返還給使用者使用 剩餘的chunk 即remainder chunk會被新增到 unsorted bin中去。如果根據使用者的需求找到對應的large bin鍊錶但是發現最大的chunk塊尺寸小於使用者所需要的尺寸 那麼這個時候就需要找到下乙個不為空的large bin。這個時候就需要檢索binmap,如果能找到符號條件的bin 則仍然按照split兩塊的形式 一塊返還給使用者 一塊掛入到unsorted bin中去若這個時候未找到!!! 此時就會從top chunk中分割一塊出來top chunk之前我們看到過 它始終位於高位址處的地方 我們稱為top chunk。它不屬於任何乙個bin中。當bins中沒有合適的chunk時 就需要到top chunk中需要合適的塊了。 如果top chunk的大小滿足使用者所要求的chunk大小 那麼會從top chunk中割下一塊給使用者作為user chunk另一塊就作為remainder chunk 即縮小的top chunk存在著。 當top chunk的大小不滿足使用者所需的尺寸大小的時候,就需要增高對應的top chunk的高度 ,對於main_arena而言 是通過sbrk()系統呼叫拔高對應的top chunk的高度 即增大top chunk的大小以滿足使用者的需求而對於thread_arena而言 則是通過mmap系統呼叫 通過heap_info資料結構將多個堆串連在一起 以使得滿足使用者的需求!!!雖然不在bins中 但會被記錄在mstate中 即malloc_state結構中

last remainder chunk**於最近一次的split操作 例如在使用者所申請的chunk_size落入對應的large bins範圍中 我們從對應的large bin中分出一塊給使用者,另一塊放入到unsorted bin中作為small bins和large bins的高速緩衝 之所以這樣是因為保證小塊可以被盡可能在虛擬位址上毗鄰 方便之後free的時候進行合併操作。按照這個示例而言 會存在remainder chunk,而最近一次由於split而進入unsorted bin的就是 last remainder chunk!!!會被記錄在malloc_state中 即mstate中

之後當使用者再次請求small chunk的時候並且如果last remainder chunk是unsorted bin中唯一的一塊chunk 那麼 last remainder chunk就會再次進行split操作 可以想象 按照這個樣子 last remainder chunk周圍的都是small chunk 當free的時候就很可能會與周圍一樣free的small chunk 進行合併操作

基礎資料結構 堆

更新完了,但是細節說的還不太夠,以後再說吧 堆的本質是乙個完全二叉樹,除了最下面一層以外,其他的每層 假設第 n 層 都有 2 n 個結點。節點存的值每層都是遞增或者遞減的。遞增的話就是大頂堆,遞減的話就是小頂堆。那麼對於大頂堆來說,每個節點的兒子節點上的值都要小於等於該節點,否則它就不是乙個堆。堆...

資料結構 堆

最大堆 最小堆 堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點...

資料結構 堆

資料結構 堆的操作和實現 當應用優先順序佇列或者進行堆排序時,一般利用堆來實現。堆是乙個完全 除最底層 外都是滿的 二叉樹,並滿足如下條件 1 根結點若有子樹,則子樹一定也是堆。2 根結點一定大於 或小於 子結點。因為要求堆必須是完全二叉樹,所以可以用線性的資料結構,比如陣列,來實現堆。利用陣列實現...