操作系统第5次实验报告:内存管理
- 姓名:朱笃信
- 学号:201821121021
- 班级:计算1811
1. 记录内存空间使用情况
用结构体的方式存放进程的起始地址,进程的分区长度,进程编号,与分区状态。
typedef struct LNode{
int address;//表示该分区的起始地址
int length; //表示该分区的长度
int state; //0表示该分区空闲,1表示该分区已分配
int number; //作业的编号
struct LNode *next;
}*pLNode;
2. 记录空闲分区
用链表的方式来记录空闲分区,代码同1,区别在于,进程占用的分区对应的状态为1,而空闲分区的状态为0。
typedef struct LNode{
int address;//表示该分区的起始地址
int length; //表示该分区的长度
int state; //0表示该分区空闲,1表示该分区已分配
int number; //作业的编号
struct LNode *next;
}*pLNode;
3. 内存分配算法
采用首次适配算法,判断内存链表中的空闲分区的大小是否满足当前进程的需求,如果内存不够:打印内存分配失败。
如果内存大小充足,则从该空闲块中划分出进程大小的分区,并修正空闲分区的起始地址与空闲大小。
void Allocation(pLNode L, int len, int num) {
pLNode p = L->next;
while (p != NULL) {
if (p->state == 0) {
//查找空闲分区
if (p->length > len) { //空闲分区大小充足
pLNode l = (pLNode)malloc(sizeof(pLNode));
l->length = p->length - len; //修正分区大小
l->address = p->address + len; //修正分区起始地址
l->state = 0;
l->number = 0;
l->next = p->next;
p->next = l;
p->length = len;
p->number = num;
p->state = 1;
printf("内存分配成功!\n");
return;
}
else if (p->length == len) {
p->number = num;
p->state = 1;
printf("内存分配成功!\n");
return;
}
}
p = p->next;
}
printf("内存分配失败,没有找到合适的空闲内存块\n");
}
4. 内存释放算法
释放单一进程的信息,查询链表中是否存在将释放的进程,若无输出查无此进程,若有,将该分区的状态更新为空闲。
void Revocation(pLNode L, int num) {
pLNode p = L->next;
while (p->next != NULL) {
if (p->number == num) {
p->state = 0;
printf("成功撤销编号为%d的作业!\n",num);
return;
}
p = p->next;
}
printf("撤销作业失败,没有找到编号为%d的作业\n", num);
}
更新链表:查询链表中是否存在相邻的两个空闲进程,将这两个空闲进程进行合并,否则可能由于某一分区大小过小导致其他进程无法使用,造成空间浪费。
void refresh(pLNode L){
pLNode p = L->next;
pLNode temp;
while(p != NULL){
if(p->next != NULL){
if(p->state == 0 && p->next->state == 0){
temp=p->next;
p->length=p->length+temp->length;
p->next=temp->next;
free(temp);
continue;
}
}
p = p->next;
}
}
5. 运行结果
(1)产生测试数据
srand((unsigned)time(NULL)); //避免较短时间内生成的随机数一样
pLNode L = (pLNode)malloc(sizeof(pLNode));
InitLNode(L, 512); //初始化内存大小
int len, num;
int a=0;
for(a=0;a<10;a++){ //随机生成10组数据
len=rand()%100; //随机生成进程长度进行测试
Allocation(L,len,1); //创建进程分区
len=rand()%100;
Allocation(L,len,2);
len=rand()%100;
Allocation(L,len,3);
print(L);
Revocation(L,1); //删除进程分区
Revocation(L,2);
Revocation(L,3);
refresh(L); //更新链表情况
}
(2)解释结果

初始运行时初始化链表,表头的节点定义为root,root进程大小为8,初始地址为0,状态显示为已分配
然后随机生成三个进程大小的进程,此处为52,17,1,则对应初始地址为:8、60、77,那么剩下的空闲分区为起始地址为78,剩余内存为434,显示状态为空闲,然后将这些进程删除,依次将这些进程对应的分区状态更改为空闲,然后使用refresh函数更新链表情况,将同样空闲的分区合并。
例如下图:

(此处代码未修正,root显示为操作系统)
此图中的第一个3进程未释放,然后创建了大小分别为68、63、57的三个进程,先分配进程1,占用8-76对应的内存,与原进程3间剩下大小为30的空闲分区,不足以让新的进程2与进程3进行使用,而3
之后的空闲分区可以使用,所以2的起始地址为124。新进程3同理。
第二次进行内存分配:

由于此处的分配是在先前三个进程都删除的情况下,所以进程1的起始是从8开始,各进程依次进行内存占用。
如果更改创建进程与删除进程的顺序,或者某些进程不删除,那么会出现如下情况:

此图可以参照图二,图二中的323进程都未删除,此时再创建3个进程,大小分别为32、11、83,由于第一个三进程的与root进程(此处为操作系统)间的空闲分区为98,可以创建进程一与进程二,而三无法创建在此段空闲分区内,故而延后值323之后。

浙公网安备 33010602011771号