操作系统第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之后。

 

posted @ 2020-05-14 22:30  duxinZhu  阅读(243)  评论(0编辑  收藏  举报