實驗總結
- 本次實驗用時約兩個小時,修改了 xv6 中大量惡臭代碼。
測試結果:
$ make grade
alloctest:
OK (7.2s)
alloctest:
OK (5.8s)
usertests:
OK (84.3s)
Score: 100/100
0. 實驗准備
上來直接:
$ cd xv6-riscv-fall19
$ git checkout alloc
實驗分為兩個子任務:
- 給 xv6 的 vfs 加上 malloc(之前是靜態內存池)
- 修改 xv6 的 buddy allocator,通過維護一對 buddy 的
B1_is_free XOR B2_is_free
這個占用狀態,節約了 ~1M 內存。
感覺是重在閱讀和理解 xv6 代碼,這兩個 lab 代碼量都很小。
1. file.c
把 filealloc()
中遍歷 ftable.file
的代碼和 fileclose()
相應的釋放代碼替換為 bd_malloc()
即可。
2. buddy.c
這個 buddy allocator 中維護了兩個 bitset ,一個存是否分裂 bd_sizes[k].split
,另一個存是否已占用 bd_sizes[k].alloc
。 只需要不斷查找 bit_*
這組工具函數出現的位置然后替換成相應的實現即可。
重難點不在於動態 malloc/free
的部分,實際上這些代碼很好改。關鍵在於 bd_initfree()
和 bd_initfree_pair()
部分。
因為 buddy allocator 管理內存的同時需要在內存區域頭部放一些 metadata,且內核提供內存區域的長度也很可能不是對其 2^k 次方的,故需要把一些區域 mark 為 allocated 。同時這些區域對應的 buddy 可能需要被加入 free_list (bd_initfree()/bd_initfree_pair()
用來完成此工作)
根據 bd_init()
中代碼:
// done allocating; mark the memory range [base, p) as allocated, so
// that buddy will not hand out that memory.
int meta = bd_mark_data_structures(p);
// mark the unavailable memory range [end, HEAP_SIZE) as allocated,
// so that buddy will not hand out that memory.
int unavailable = bd_mark_unavailable(end, p);
void *bd_end = bd_base+BLK_SIZE(MAXSIZE)-unavailable;
// initialize free lists for each size k
int free = bd_initfree(p, bd_end, p, end);
這些不可用內存對應的內存區間為 [begin, p)
和 [end, HEAP_SIZE)
。在 bd_initfree_pair()
中特判這些內存范圍,就可以把他們的 buddy 識別出來,而無需查找 bd_sizes[k].alloc
。