TLSF算法主要是面向實時操作系統提出的,對於RTOS而言,執行時間的確定性是最根本的(吞吐量不壹定高),然而傳統的動態內存分配器(DMA, Dynamic Memory Allocator)存在兩個主要問題
TLSF的提出較好地解決了以上兩個問題: 將動態內存的分配與回收時間復雜度都降到了O(1)時間復雜度,並且采用了Good-fit的分配策略保證系統運行時不會產生過多碎片。
TLSF(全稱Two-Level Segregated Fit),從命名來看主要分為三部分
TLSF主要采用兩級位圖(Two-Level Bitmap)與分級空閑塊鏈表(Segregated Free List)的數據結構管理動態內存池(memory pool)以及其中的空閑塊(free blocks),用Good-Fit的策略進行分配。下面我們先簡單介紹壹下這三者。
還是采用拆分理解的方式,繼續把Segregated Free List拆開,探究其設計思路和發展演變過程
鏈表是內存管理中最常見的數據結構,在壹塊內存塊頭部添加壹個頭結點,記錄該block本身的信息以及前後繼block的關系。
其中最簡單的壹種就是 隱式鏈表 ,鏈接 所有內存塊 , 只記錄內存塊大小,由於內存塊緊密相連,通過頭結點指針加內存塊大小即可得到下壹個內存塊的位置。由於沒有顯式指明內存塊的地址,而是通過計算得到,所以又叫做隱式鏈表。
當需要分配內存時,需要從第壹塊內存塊開始檢索,檢查該內存塊是否被分配以及內存塊大小是被滿足,直到找到大小合適的空閑塊分配出去。
上面提到的隱式鏈表和顯式鏈表主要問題在於當空閑塊個數為n時,檢索復雜度在O(n)級別,速度較慢,分級空閑塊鏈表優化了空閑塊檢索的復雜度,粗略計算大概降到O(log(n))級別。
分級空閑塊鏈表(Segregated Free List)的設計思想是將空閑塊按照大小分級,形成了不同塊大小範圍的分級(class),組內空閑塊用鏈表鏈接起來。每次分配時先按分級大小範圍查找到相應鏈表,再從相應鏈表挨個檢索合適的空閑塊,如果找不到,就在大小範圍更大的壹級查找,直到找到合適的塊分配出去。
上面我們介紹了分級空閑塊鏈表的原理,但是我們並沒有提及如何按照內存塊大小分級。TLSF算法引入了位圖(Bitmap)來解決這個問題。
當分級空閑塊鏈表碰上位圖,動態內存管理結構變化稍微有些大,下面這張圖畫得還算清晰(能依稀看到分級空閑塊鏈表的影子就好:-P)。
TLSF采用了兩級位圖(Two-Level Bitmap)來管理不同大小範圍的空閑塊鏈(free block lists)。 上圖中包含三個虛線矩形框分別是:
有了TLSF的大體框架概念以後,就可以先看壹下內存alloc與free的簡要流程。(細節下壹節結合源碼探討)
內存分配流程
內存釋放流程
內存結構和分配釋放流程已經有了大致的了解,但是其中還有壹個小問題並沒有說明:
常規思路是:找到能滿足內存請求大小的最小空閑塊,就會有下面的流程(以搜索大小為69字節的空閑塊為例)
看起來Best-fit 已經很不錯了,但仍然還有提升空間。Best-fit策略最主要的問題還在於第三步,仍然需要檢索對應範圍的那壹條空閑塊鏈表,存在潛在的時間復雜度。
Good-fit思路與Best-fit不同之處在於,Good-fit並不保證找到滿足需求的最小空閑塊,而是 盡可能接近 要分配的大小。
還以上述搜索大小為69字節的空閑塊為例,Good-fit並不是找到[68 ~ 70]這壹範圍,而是比這個範圍稍微大壹點兒的範圍(例如[71 ~ 73])。這樣設計的好處就是[71 ~ 73]對應的空閑塊鏈中每壹塊都能滿足需求,不需要檢索空閑塊鏈表找到最小的,而是直接取空閑塊鏈中第壹塊即可。整體上還不會造成太多碎片。
這壹節我們扒壹扒LiteOS的源碼,分析其中的數據結構和內存布局。
空閑塊和使用塊復用同壹數據結構,但在使用時並非所有字段都使用。
主要參考下面這兩篇博客,從安裝eclipe、配置到項目編譯運行,挺完整的,Mac下也沒什麽問題,就是eclipse有點卡-_- !
Windows10如何安裝LiteOS開發環境(壹)
Windows10如何安裝LiteOS開發環境(二)
提個醒: