// compute the number of sizes we need to manage [base, end)
nsizes = log2(((char *)end-p)/LEAF_SIZE) + 1;
if((char*)end-p > BLK_SIZE(MAXSIZE)) {
nsizes++; // round up to the next power of 2
}
printf("bd: memory sz is %d bytes; allocate an size array of length %d\n",
(char*) end - p, nsizes);
// allocate bd_sizes array
bd_sizes = (Sz_info *) p;
p += sizeof(Sz_info) * nsizes;
memset(bd_sizes, 0, sizeof(Sz_info) * nsizes);
// initialize free list and allocate the alloc array for each size k
for (int k = 0; k < nsizes; k++) {
lst_init(&bd_sizes[k].free);
sz = sizeof(char)* ROUNDUP(NBLK(k), 16)/16;
bd_sizes[k].alloc = p;
memset(bd_sizes[k].alloc, 0, sz);
p += sz;
}
// allocate the split array for each size k, except for k = 0, since
// we will not split blocks of size k = 0, the smallest size.
for (int k = 1; k < nsizes; k++) {
sz = sizeof(char)* (ROUNDUP(NBLK(k), 8))/8;
bd_sizes[k].split = p;
memset(bd_sizes[k].split, 0, sz);
p += sz;
}
p = (char *) ROUNDUP((uint64) p, LEAF_SIZE);
int bit_isset(char *array, int index) {
char b = array[index/8];
char m = (1 << (index % 8));
return (b & m) == m;
}
// Set bit at position index in array to 1
void bit_set(char *array, int index) {
char b = array[index/8];
char m = (1 << (index % 8));
array[index/8] = (b | m);
}
// Clear bit at position index in array
void bit_clear(char *array, int index) {
char b = array[index/8];
char m = (1 << (index % 8));
array[index/8] = (b & ~m);
}
而mate date肯定不能再进行分配,所以进行标记
// 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);
//........
// initialize free lists for each size k
int free = bd_initfree(p, bd_end);
// Initialize the free lists for each size k. For each size k, there
// are only two pairs that may have a buddy that should be on free list:
// bd_left and bd_right.
int
bd_initfree(void *bd_left, void *bd_right) {
int free = 0;
for (int k = 0; k < MAXSIZE; k++) { // skip max size
int left = blk_index_next(k, bd_left);
int right = blk_index(k, bd_right);
free += bd_initfree_pair(k, left, 1);
if(right <= left)
continue;
free += bd_initfree_pair(k, right, 0);
}
return free;
}
找每个不同大小块的位置是通过和bd_base位置距离进行判断
// Compute the block index for address p at size k
int
blk_index(int k, char *p) {
int n = p - (char *) bd_base;
return n / BLK_SIZE(k);
}
// Compute the first block at size k that doesn't contain p
int
blk_index_next(int k, char *p) {
int n = (p - (char *) bd_base) / BLK_SIZE(k);
if((p - (char*) bd_base) % BLK_SIZE(k) != 0)
n++;
return n ;
}
// If a block is marked as allocated and the buddy is free, put the
// buddy on the free list at size k.
int
bd_initfree_pair(int k, int bi) {
int buddy = (bi % 2 == 0) ? bi+1 : bi-1;
int free = 0;
if(bit_get(bd_sizes[k].alloc, bi)) {
// one of the pair is free
free = BLK_SIZE(k);
if(bit_isset(bd_sizes[k].alloc, bi))
lst_push(&bd_sizes[k].free, addr(k, buddy)); // put buddy on free list
else
lst_push(&bd_sizes[k].free, addr(k, bi)); // put bi on free list
}
return free;
}
所以这里优化通过异或来代表一对buddy来缩小空间。以达到可以分配更多的内存
int bit_get(char *array, int index) {
index >>= 1;
char b = array[index/8];
char m = (1 << (index % 8));
return (b & m) == m;
}
我太菜了
lab3
Lab: Allocator for xv6
File Buddy
file.c
没什么说的,用bd_malloc
动态分配struct file
替换struct file file[NFILE];
静态分配来突破NFILE
数量的限制。记得fileclose
的时候bd_free
掉buddy.c
修改的代码量很少,主要是要看懂它怎么实现。重点在bd_init
函数先理解
buddy system
先给
meta date
分配内存,也就是struct sz_info
结构体Bd_list free
双向链表管理需要分配的每块内存chra *alloc
标记是否分配的tagchar *split
标记对应是否分裂内存分部大概如下
其中
alloc
1byte能表示0x10*8
的内存地址,1bit代表0x10
其中
bit_xxx
操作就是通过位运算来实现的.一段0x80的内存已经被分配那么bit为
11111111
,也就是f而mate date肯定不能再进行分配,所以进行标记
而且在0x8032a310和最后的位置位置相邻的位置就是mate date肯定不能当buddy进行分裂,所以提前把这两个地址放入list里面
找每个不同大小块的位置是通过和bd_base位置距离进行判断
改动
这里可以发现alloc占了内存
0x20000
似乎大小刚好管理分配的内存
但是这里可以优化。
可以省10000h的空间,
sz = sizeof(char)* ROUNDUP(NBLK(k), 8)/8;
缩小成sz = sizeof(char)* ROUNDUP(NBLK(k), 16)/16;
原来一对一的映射变成一对一对buddy,空间缩小了一半
通过在free或者malloc的时候只需要判断它的buddy是否分配。粗暴点的方法就是每一bit代表一块,只需要用
bit_isset
判断是否被标记就行了。但是更简便的方式是将这一对buddy看成一块,只需要用异或判断对应buddy的状态就可以知道是否被占用。
这里最代表的是
if(bit_get(bd_sizes[k].alloc, bi))
就能判断buddy是否被分配所以这里优化通过异或来代表一对buddy来缩小空间。以达到可以分配更多的内存
bd_malloc
和bd_free
还是很容易修改,重点还是在bd_init
去处理边界的时候需要额外判断处理具体看源码= =