chunk可以分成allocated chunk,free chunk,top chunk,last remainter chunk
由於在libc2.26之後引入tcachebins,所以堆分配機制和之前不太相同
tcachebins——tcachebins是乙個長度為64的位元組陣列,每個位元組陣列對應一條鍊錶。所以tcachebins只能存放0x0-0x400大小的堆,且每個鍊錶長度為7。並且類似於fastbins,是乙個單鏈表。在釋放大小為0x0-0x400大小的堆的時候,首先會被釋放入對應長度tcachebins對應的鍊錶中,當長度超出7後,再放入fastbin或unsortbins中。malloc的時候當發現malloc對應大小的堆,先從tcachebins中取出。注意當如果從fastbin中取出了乙個塊,那麼會把剩餘的塊放入tcache中直至填滿tcache(smallbin中也是一樣)。如果進入了unsortedbin,且chunk的size和當前申請的大小精確匹配,那麼在tcache未滿的情況下會將其放入到tcachebin中
fastbins——fastbins上有7個單鏈表,是bins陣列上的前十位,存放大小為0x20-0x80的堆,存放時不合併
sortbins——當有大於0x400或在0x80-0x400的時候tcachebins以存放滿,多餘的堆將讓放入sortbins。
smallbins——通常是在對sortbins和fastbins整理後放入
獲取分配區的鎖,防止多執行緒衝突。
計算出實際需要分配的記憶體的chunk實際大小。
先從tcachebins中查詢是否有對應大小堆塊,如果存在將先從tcachebins中取出。
判斷chunk的大小,如果小於max_fast(128b),則嘗試去fast bins上取適合的chunk,如果有則分配結束,並將剩餘的塊放入tcachebins直到存滿。否則,下一步;
判斷chunk大小是否小於1024b,如果是,則從small bins上去查詢chunk,如果有合適的,則分配結束,並將剩餘的塊放入tcachebins直到存滿。下一步;
判斷chunk大小是否小於1024b,如果是,如果unsorted bin中有滿足chunk大小的,則直接切割返回。並將unsorted bin中剩下的部分整理入small bins和large bins上。否則直接整理。否則操作top chunk。
當申請大於1024b,ptmalloc首先會遍歷fast bins中的chunk,將相鄰的chunk進行合併,並鏈結到unsorted bin中然後遍歷 unsorted bins。如果unsorted bins上只有乙個chunk並且大於待分配的chunk,則進行切割,並且剩餘的chunk繼續扔回unsorted bins;如果unsorted bins上有大小和待分配chunk相等的,則返回,並從unsorted bins刪除;如果unsorted bins中的某一chunk大小 屬於small bins的範圍,則放入small bins的頭部;如果unsorted bins中的某一chunk大小 屬於large bins的範圍,則找到合適的位置放入。若未分配成功,轉入下一步;
從large bins中查詢找到合適的chunk之後,然後進行切割,一部分分配給使用者,剩下的放入unsorted bin中。
如果搜尋fast bins和bins都沒有找到合適的chunk,那麼就需要操作top chunk來進行分配了
當top chunk大小比使用者所請求大小還大的時候,top chunk會分為兩個部分:user chunk(使用者請求大小)和remainder chunk(剩餘大小)。其中remainder chunk成為新的top chunk。
當top chunk大小小於使用者所請求的大小時,top chunk就通過sbrk(main arena)或mmap(thread arena)系統呼叫來擴容。
到了這一步,說明 top chunk 也不能滿足分配要求,所以,於是就有了兩個選擇: 如 果是主分配區,呼叫 sbrk(),增加 top chunk 大小;如果是非主分配區,呼叫 mmap 來分配乙個新的 sub-heap,增加 top chunk 大小;或者使用 mmap()來直接分配。在 這裡,需要依靠 chunk 的大小來決定到底使用哪種方法。判斷所需分配的 chunk 大小是否大於等於 mmap 分配閾值,如果是的話,則轉下一步,呼叫 mmap 分配, 否則跳到第 10 步,增加 top chunk 的大小。
使用 mmap 系統呼叫為程式的記憶體空間對映一塊 chunk_size align 4kb 大小的空間。 然後將記憶體指標返回給使用者。
判斷是否為第一次呼叫 malloc,若是主分配區,則需要進行一次初始化工作,分配 一塊大小為(chunk_size + 0x250) 大小的空間作為初始的 heap。若已經初 始化過了,主分配區則呼叫 sbrk()增加 heap 空間,分主分配區則在 top chunk 中切 割出乙個 chunk,使之滿足分配需求,並將記憶體指標返回給使用者。
簡而言之: 獲取分配區(arena)並加鎖–> fast bin –> unsorted bin –> small bin –> large bin –> top chunk –> 擴充套件堆
獲取分配區的鎖,保證執行緒安全。
如果free的是空指標,則返回,什麼都不做。
判斷當前chunk是否是mmap對映區域對映的記憶體,如果是,則直接munmap()釋放這塊記憶體。前面的已使用chunk的資料結構中,我們可以看到有m來標識是否是mmap對映的記憶體。
判斷chunk是否在tcachebins範圍內且tcachebins對應位置未滿,如果滿足,加入tcachebins中,否則進入下一步
判斷chunk是否與top chunk相鄰,如果相鄰,則直接和top chunk合併(和top chunk相鄰相當於和分配區中的空閒記憶體塊相鄰)。轉到步驟8
如果chunk的大小大於max_fast(64b),則放入unsorted bin,並且檢查是否有合併,有合併情況並且和top chunk相鄰,則轉到步驟8;沒有合併情況則free。
如果chunk的大小小於 max_fast(64b),則直接放入fast bin,fast bin並沒有改變chunk的狀態。沒有合併情況,則free;有合併情況,轉到步驟7
在fast bin,如果當前chunk的下乙個chunk也是空閒的,則將這兩個chunk合併,放入unsorted bin上面。合併後的大小如果大於64b,會觸發進行fast bins的合併操作,fast bins中的chunk將被遍歷,並與相鄰的空閒chunk進行合併,合併後的chunk會被放到unsorted bin中,fast bin會變為空。合併後的chunk和topchunk相鄰,則會合併到topchunk中。轉到步驟8
判斷top chunk的大小是否大於mmap收縮閾值(預設為128kb),如果是的話,對於主分配區,則會試圖歸還top chunk中的一部分給作業系統。free結束。
記憶體管理機制
記憶體管理 jvm將記憶體分成三大主要區域 堆,棧,方法區,用來儲存資料。堆 堆中主要儲存引用型別物件,給成員變數分配空間。棧 jvm在執行程式時,在棧中會為每乙個方法都提供儲存空間叫棧幀,用來儲存方法中的區域性變數。方法區 用來儲存jvm載入的位元組碼檔案的資訊 類的資訊 包含類的方法,方法只有乙...
記憶體管理機制
記憶體管理是乙個作業系統必不可少 並且 非常重要的一環 linux 的成功 和它優秀的記憶體管理聯絡非常密切 因為乙個系統的高效性慾穩定性往往決定於它的記憶體管理機制 我項很多人吃過 dos 下 640k 的苦吧 前面我們介紹了 386 保護模式 從今天起我們將在此基礎上 分析 linux 的虛擬儲...
Redux管理機制
redux是乙個獨立專門用於做狀態管理的js庫,不是react外掛程式。作用 集中式管理react應用中多個元件共享的狀態和從後台獲取的資料。使用react redux簡化redux的編碼 使用redux thunk實現redux的非同步編碼 使用redux devtools實現chrome中red...