contributed by < yanjiew1
>
1
mpool
為 memory pool 實作。
pool_init
是用來初始化 mpool
系統,透過它告訴 mpool
使用哪塊空間作為 memory pool 使用 ,空間大小有多少。
mpool
實作了類似 C 語言標準函式庫提供的記憶體配置器函式,分別為 pool_malloc
、 pool_calloc
、 pool_realloc
、 pool_free
。功能與 C 語言的記憶體置器很像,差別在於 mpool
是從一個設定好的一塊 memory pool 來配置空間。
已配置的空間為系統 word size 大小的 size
和 payload
組成。malloc
會回傳 payload
部份的指標。payload
為使用 mpool
程式可以利用的空間。
未配置空間除了 size
外,後面還會接續 prev
和 next
二個指標,分別指向上一個和下一個未配置空間。
上述二種狀態都可用 block_t
結構來表示。size
為已配置和未配置空間都會使用的欄位,而 prev
和 next
只會在未配置空間使用。
pool_init
程式一開始會呼叫 pool_init
來告訴 mpool
可以使用哪塊空間作為 memory pool 。函式中會檢查大小是否大於 header_size
(即 3 個 word size) ,若大小小於 head_size
代表連未配置空間的標頭都放不下,無法使用。
pool_init
也會設定全域變數 pool_size
和 pool_free_space
。 pool_size
為總共 memory pool 空間, pool_free_space
為未配置空間。這二個空間都要減去 word_size
是因為即使一次把整塊空間都配置出去,其最前面的標頭還是需要放配置出去的空間大小,故使用者可用的空間需要減去 word_size
。
pool_init
會把傳入的空間放到 free list 上,並寫入未配置空間的標頭,即 size
、 prev
和 next
。 程式中的 current
為 free list 。
pool_malloc
pool_malloc
會從 memory pool 配置空間。配置時,會使用 round_up
取得大於等於 size
的最小可以被 word_size 整除的數字,作為真正配置的空間。這樣做是為了讓得到的記憶體空間都能跟 word size 對齊,避免出現未對齊的操作。其中 round_up
實作如下:
其實就是先把原本的數加上 7 再 round down 至 word size。
但這裡有問題是, + 7
是針對 64 bits 系統 (word size 為 8 bytes), 32 bits 系統應該要 + 3
(word size 為 4 bytes)。 雖然在 32 bits 系統也能用,但會造成空間浪費。
TODO: 學習 Linux 核心的 ilog2,編譯時期決定要調整的空間。
jservImage Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
接著 pool_malloc
會透過 get_loc_to_place
用 first-fit 的演算法,從 free list 中找到一塊可用的空間。 get_loc_to_place
會先檢查 current
指標所指向的空間是否可用,若不可用則會先走訪 prev
指標,若仍然未找到可用的空間再走訪 next
指標。
程式有錯誤。在走訪 next
指標是,應該是由 ((block_t *) current)->next
開始走訪,而不是 ((block_t *) current)->prev
。這樣子導致當 ((block_t *) current)->prev
為 NULL
時,無法正常配置空間,即使走訪 next
有可用的空間。
此外,這裡確保取得的空間有 size + header_size
,是因為在 pool_malloc
中,會把一個 free block 的前半部分配出去,後半部作為剩下的空間, pool_malloc
沒有考慮到整塊空間配置出去的情況,一定會留下一個 free block 。
呼叫 get_loc_to_place
取得可用的 block 。回傳值設為取得的空間加上 word size 。因為最前面要存放 size
。
程式錯誤:
get_loc_to_place
取得 free block 後,卻又把 current
指向的 free block 配置出去,沒有利用到 get_loc_to_place
找到的空間。size
欄位。從 current
配置空間後,備份原本 current
的 prev
和 next
指標,並設定把 current
設定成新的 free block 。
當 new_size
小於 0 時,會放棄設定新的 free block ,但裡面有把 current->size
指定為 0 ,可能就覆寫到其他空間了。此外如果要有足夠空間存放新的 free block ,至少 new_size
要有二個 word size 的空間才夠,但這裡也沒考慮到。
不過因為前面的程式已經錯了,所以後面的程式自然就接連有問題。
最後更新前後 free blocks 的指標:
pool_calloc
pool_calloc
可以利用原有的 pool_malloc
,再把新配置的空間填 0 。
pool_realloc
pool_realloc
重新呼叫 pool_malloc
配置新空間,再把原有的內容拷貝過去,再把原有的空間釋放。
pool_free
取得傳入位址的包含標頭的位址。因為知道所有經由 mpool
配置出來的空間前一個 word ,就是記錄配置空間的大小。
使用 get_loc_to_free
取得鄰近的 free block
若找到的 free block 與傳入要釋放的記憶體相鄰,則將此 free block 與目前要釋放的記憶體合併。
若 free_pt
與 block_pt
不相鄰怎麼辦? 這樣子 block
內的 prev
和 next
就沒被設置。 pool_free
顯然沒考慮此情況,會產生不可預期的結果。
最後再嘗試合併相鄰的 free block 。
mpool
不論是 pool_malloc
或是 pool_free
都有明顯的錯誤。pool_realloc
採用重新配置空間的策略,沒有考慮是不有可能就地縮小或增加空間,也還有改進的空間。在 pool_free
需要再走訪 free list ,才能找到鄰近的 free block ,時間複雜度為 較沒效率。
可對照 CS:APP 第 9 章閱讀。
jservImage Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
此外程式碼註解的英文有許多文法或單字錯誤,註解很難閱讀。
其實一開始是給 ChatGPT 的 prompt
jservImage Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
嘗試保留原有的程式碼,但修復程式中的錯誤。
2