contributed by < zeddyuu >
1
程式一開始宣告了名為 block 的結構體來存放 metadata,有 size 代表實際存放的資料大小以及 prev 和 next 指標指向前一個和下一個 block,並且根據硬體架構是 32 bit 或是 64 bit 定義了 word_size 為多少 bytes。
接著說明每個函式的運作流程及功能
pool_init()
此函式用作初始化一個 memory pool,會在系統啟動時呼叫,會先檢查傳入的位址是否合法,以及檢查傳入欲創建的大小是否大於 header_size,也就是一個 free block 必須儲存的 metadata 大小 (size, prev, next),若檢查失敗則直接回傳錯誤,確認無誤後即開始設定一些全域變數,欲配置的 size 都必須先減掉 word_size 再賦值給 pool_size 以及 pool_free_space 紀錄,原因是因為若初始化完成後馬上全部配置出去成為 In-use block 也必須儲存 size 的資訊。
pool_malloc()
分配參數 size 大小的記憶體,但分配之前會先對 size 進行 round up,以配合硬體架構使其可以為暫存器大小的倍數
但這裡 round up 的寫法只適用於 64 bit 的系統,也就是以 8 bytes 進行 round up,若為 32 bit 的系統應該要是 (*x + 3) 才對,可用 bitwise 的方法稍微改寫。
接著檢查 memory pool 的 free space 大小是否足夠分配 round up 後的 size 的量加上 header_size,若足夠則用 get_loc_to_place
找出一個大小足夠置放的 free block 記憶體位址,但在 get_loc_to_space
中發現一個錯誤是在往後找 block 時的迴圈初始化設定錯誤,應該要從 current->next 開始找起而不是 current->prev
但奇怪的是在找到可放入的 block 後,卻沒有利用這塊找到的空間,而是直接用 current 當作可用的空間,且在 get_loc_to_space
其實也有檢查 current,故這可能會導致因為 current 其實沒有足夠的空間而發生錯誤,且在分配空間之後並沒有更新 pool_free_space 變數
pool_calloc()
利用 pool_malloc()
分配記憶體,並且將記憶體內存的值設為 0
pool_realloc()
利用 pool_malloc()
重新分配一個大小不同的記憶體空間,且新的記憶體內容會使用給定的 addr 記憶體內容進行複製
pool_free()
將分配的記憶體釋放掉,利用 get_loc_to_free
去找出鄰近的 free block 用於合併,這邊注意到 get_loc_to_free
中回傳的變數型態應該要是 void * (實際上是 block_t *),但在這個函式中的回傳型態為指標變數的記憶體位置,也就是要用指標的指標 block_t ** 去做顯式轉型,但這邊卻用了 block_t * 去做轉型,根據函式的目的應該只需要回傳 block_t *,只要將取址運算子 & 拿掉即可修正錯誤。
參考 void * 之謎
接著就是對找出的 free block 去確認是否可以跟欲釋放的 block 進行合併,合併完成之後再對相鄰的 block 確認一次合併條件進行合併。
只要重新實作尋找 free block 的 get_loc_to_place()
函式即可,如果要找最適合的一定要每個 free block 都尋訪並跟當前最接近的 size 比較更新過後才能決定,因 bestfit_block 初值為 NULL,若過程中都沒找到也不會進行更新,故最後直接回傳 bestfit_block 即可,複雜度是 ,bestfit 的演算法會造成計算上的負擔以及讓分配記憶體的複雜度變高,整體速度變慢
2