Try to be kind and useful.

Lab2-1-Extra——一个可能的解决思路

题目要求对物理空间的高32MB地址空间建立伙伴关系,我在这里简单梳理一下我基于数组的实现,由于课上构思比较紧张,代码有些写的不妥的地方请海涵。

首先建立用于存储区间信息的结构体:

typedef struct Buddy{
u_int start;
u_int size;
u_int time;
u_int mode;
u_int f;
}Buddy;

Buddy buddy[100000];
int tot;
int time;

其中,start代表该区间的起始位置;

size代表区间大小;

time是一个比较特殊的量,记录该区间是第几次分裂而来,初始化为0;

mode代表区间状态,1代表已分配,0代表未分配,还有-1会表示一个比较特殊的状态(已分裂),后续会详细解释;

f也是一个比较特殊的量,记录着该区间是由数组中那个元素分裂而来,初始化为-1;

tot记录目前boddy的个数,初始化为0。

这里buddy数组我预留了100000,比较保守。

buddy_init的思路:

只需要从 0x2000000以起始位置实现8个buddy并存入数组中即可。

void buddy_init(void) {
u_int start = 0x2000000;
u_int size = 0x400000;
int i;
tot = 8;
time = 0;
for (i = 0; i < 8; i++) {
//一些初始化操作
}
//printf("buddy init finish");
}

buddy_alloc的思路:

大体分为3步:

  1. 寻找符合要求的地址最低的区间

  2. 针对该区间进行分裂操作

  3. 获取各种需要的信息并返回

int buddy_alloc(u_int size, u_int *pa, u_char *pi) {
u_int min = 0x4000010;
int index = 0;
int i;
for (i = 0; i < tot; i++) {
//(1)寻找符合要求的地址最低的区间
}
if (min == 0x4000010) {
       //没找到
return -1;
}
int pos = findMin(index, size);//(2)进行分裂操作

   
//(3)获取输出信息


return 0;
}

可以看到,上述比较关键的是进行分裂操作的函数,此处我写的是一个findMin递归函数,核心就是将区间分裂,但不删除旧的区间,仅在数组最后添加新的子区间,并标记旧区间的状态为-1,新子区间的f记为旧区间的下标,更新time并标记到新增子区间。

int findMin(int i, u_int size) {
if (buddy[i].size / 2 < size || buddy[i].size == 0x1000) {
buddy[i].mode = 1; //(1)找到了合适的区间
return i;
}
time++;
//(2)新增两个子区间
return findMin(tot-2, size);//递归分裂
}

buddy_free的思路:

分两步:

1.寻找满足起始地址为pa的区间并改变其状态为未分配

2.合并可能合并的区间

void buddy_free(u_int pa) {
int i;
   //(1)寻找满足条件的区间,采用倒序,效率高一些
for (i = tot - 1; i >= 0; i--) {
if (buddy[i].mode == 1 && buddy[i].start == pa) {
break;
}
}
buddy[i].mode = 0;
   //(2)合并可能的区间
if (buddy[i].time != 0) {
merge(buddy[i].time);
}
}

上述的关键也是merge函数,本处我是递归实现的:

void merge(u_int time) {
int a = -1, b = -1, i;
int flag = 0;
   //获取两个可能可以合并的区间
for (i = tot - 1; i >= 0; i--) {
if (buddy[i].mode == 0 && buddy[i].time == time) {
if (a == -1) {
a = i;
} else {
b = i;
flag = 1;
break;
}
}
}
if (flag) {
buddy[a].mode = -1;
buddy[b].mode = -1;
       //唤醒他们的父区间,并让两个子区间进入异常态实现舍去。
buddy[buddy[a].f].mode = 0;
if ( buddy[buddy[a].f].time != 0) {
merge(buddy[buddy[a].f].time);
           //递归合并可能的区间
}
}
}

总结:

对于本题,我采用了数组实现的方法,为了避免TLE,想到了分裂时并不删除区间的方法,其实是以空间换时间,或许可以尝试链表实现的方法,可能更优雅和高效。

posted @ 2022-04-14 23:31  重结晶  阅读(408)  评论(0编辑  收藏  举报