目的: 檢驗學員對記憶體管理、紅黑樹,和並行程式設計的認知
作答表單: 測驗 1-2 (針對 Linux 核心「設計」/「實作」課程)
1
在第一次作業的解說、〈你所不知道的 C 語言:記憶體管理、對齊及硬體特性〉和〈你所不知道的 C 語言:函式呼叫篇〉提到記憶體配置器的實作考量,我們可將這部份的認知應用於 memory pool,程式碼可見: mpool
mpool.h
: 規範公開介面,包含 pool_init
, pool_malloc
, pool_calloc
, pool_realloc
, pool_free
等函式mpool.c
請補完程式碼,使其運作符合程式註解提及的行為。作答規範: (皆不包含小括號 [即 (
和 )
])
AAAA
, BBBB
, CCCC
, DDDD
, FFFF
, GGGG
, HHHH
皆為 identifier,不是常數或 integer literalEEEE
: 變數名稱延伸問題:
2
延伸測驗 1
,我們可運用在〈並行和多執行緒程式設計〉和〈Linux 核心的紅黑樹〉所學,建構實際可在 GNU/Linux 運作的記憶體管理器。
簡易的 malloc 實作,可運用 sbrk 系統呼叫,用法是 sbrk(size)
,後者是回傳原本的起始位置:
sbrk(0)
回傳 heap 的終點sbrk(size)
回傳 (目前的 heap 終點位置 - size),即增加 size 之前的終點位置爲了確保 heap 內的記憶體是連續的,因此不能任意將中間的記憶體釋放回作業系統,於是需要一個機制以確認,heap 內的某個部分的記憶體是否爲 free。有了該機制,即可就能確保在 free 後,heap 內的記憶體還是連續的。
另一個好處是,每次呼叫 malloc
時不用頻繁呼叫 sbrk,而是去 heap 中尋找能否有空閒且足夠的記憶體即可。為此,我們需要一個結構在每塊記憶體的前面,size 用來知道這塊 block_meta_t
所管理的記憶體大小,next
則連接到下一塊 block_meta_t
,然後我們需要一個指標global_base
來記錄開頭節點:
每塊記憶體前面都必須要有這塊 block_meta_t
,因此每次 malloc 時都需要更動爲:
接下來,實作一個在所有 block 中尋找能否使用的空間,last
用來記錄最後的 block 在哪裏,程式碼如下:
如果在目前的 heap 中找不到一塊空閒且足夠大小的空間,那就必須申請 sbrk 增加 heap 的大小,在上方 find_free_block
已找到 last
,因此申請新的 block 時,只需將 last 跟 block 連接在一起就好:
準備工作都完成,利用上方函式來實作 malloc 進入點 malloc(0)
。爲了在 free
時以安全通過,因此每次 malloc(0)
都回傳一個 NULL
:
如此,簡易的 malloc
即可實作。本題額外考慮多執行緒環境,並運用紅黑樹來建構記憶體配置器,程式碼可見 alloc.c,編譯方式: (部分遮蔽)
測試方式:
關於此處 LD_PRELOAD
,可對照看〈你所不知道的 C 語言:動態連結器篇〉。
請補完程式碼,使上述記憶體配置器得以正確運作。作答規範:
IIII
和 JJJJ
是表示式,皆不包含小括號KKKK
和 LLLL
是表示式,需要呼叫 POSIX Thread 規範的函式