操作系统第5次实验报告:内存管理
- 姓名:蒋浩天
- 学号:201821121024
- 班级:计算1811
1. 记录内存空间使用情况
创建结构体链表记录内存空间的使用情况,使用一个全局变量记录该链表的首指针。
//记录已使用内存空间 typedef struct used_block{ int pid;//进程id int size;//内存大小 int start_addr;//首地址 char process_name[PROCESS_NAME_LEN];//进程名 struct allocated_block *next; }UB; //记录已使用内存空间链表首指针 UB *used_block_head = NULL;
2. 记录空闲分区
同样创建结构体链表记录空闲内存空间的使用情况,使用一个全局变量记录该链表的首指针。
//记录空闲分区 typedef struct free_block{ int size;//大小 int start_addr;//起始地址 struct free_block_type *next; }FB; //记录空闲分区链表首指针 FB *free_block;
3. 内存分配算法
使用最佳分配算法,每次分配都将最小块的满足需求空闲分区拿去分配。内存空间按空闲区从小到大排序。
分配内存,如果找到可满足空闲分区且分配后剩余空间足够大,则分割;如果找不可满足需要的空闲分区,但空闲分区之和能满足需要,则采用内存紧缩技术,进行空闲分区的合并,然后再分配;
int allocate_mem(UB *ab){ /*分配内存模块*/ FB *fbt,*pre; int request_size=ab->size; fbt = pre = free_block; //尝试寻找可分配空闲 int f = find_free_mem(request_size); if(f == -1){ //不够分配 printf("Free mem is not enough,Allocate fail!\n"); return -1; }else{ if(f == 0){ //需要内存紧缩才能分配 memory_compact(); } //执行分配 do_allocate_mem(ab); } //重新排布空闲分区 rearrange_BF(); return 1; } //执行分配内存 void do_allocate_mem(UB *ab){ int request = ab->size; FB *tmp = free_block; while(tmp != NULL){ if(tmp->size >= request){ //分配 ab->start_addr = tmp->start_addr; int shengyu = tmp->size - request; if(shengyu <= min_mem_size){ //剩余过小全部分配 ab->size = tmp->size; if(tmp == free_block){ free_block = free_block->next; free(tmp); }else{ FB *t = free_block; while(t->next != tmp){ t = t->next; } t->next = tmp->next; free(tmp); } }else{ //切割出分配走的内存 tmp->size = shengyu; tmp->start_addr = tmp->start_addr + request; } return ; } tmp = tmp->next; } }
内存空间按空闲区从小到大排序
void rearrange_BF(){//最佳适应算法,空闲分区按大小从小到大排序 if(free_block == NULL || free_block->next == NULL) return; FB *t1,*t2,*head; head = free_block; for(t1 = head->next;t1;t1 = t1->next){ for(t2 = head;t2 != t1;t2=t2->next){ if(t2->size > t2->next->size){ int tmp = t2->start_addr; t2->start_addr = t2->next->start_addr; t2->next->start_addr = tmp; tmp = t2->size; t2->size = t2->next->size; t2->next->size = tmp; } } } }
4. 内存释放算法
根据进程号查找该进程节点,找到该节点释放该节点的分配空间和该结构节点。
//终止进程 int end_process(int p){ UB *ab; printf("Kill Process,pid= %d\n",p); ab = find_process(p); if(ab!=NULL){ free_mem(ab); //释放该节点的分配空间 dispose(ab); //释放该数据结构节点 return 0; }else{ return -1; } }
查找节点
//找到pid对应的链表节点 UB *find_process(int pid){ UB *tmp = allocated_block_head; while(tmp != NULL){ if(tmp->pid == pid){ return tmp; } tmp = tmp->next; } printf("Cannot find pid:%d\n",pid); return NULL; }
释放结构节点和结构空间
//释放链表节点 int dispose(UB *free_ab){ /*释放ab数据结构节点*/ UB *pre,*ab; if(free_ab == allocated_block_head){ //如果要是释放第一个节点 allocated_block_head = allocated_block_head->next; free(free_ab); return 1; } pre = allocated_block_head; ab = allocated_block_head->next; while(ab!=free_ab){ pre = ab; ab = ab->next; } pre->next = ab->next; free(ab); return 2; } //释放进程所占用的内存 int free_mem(UB *ab){ /* 将ab所表示的已分配区归还,并进行可能的合并 */ int algorithm = ma_algorithm; FB *fbt,*pre,*work; fbt = (FB*)malloc(sizeof(FBT)); if(!fbt) return -1; fbt->size = ab->size; fbt->start_addr = ab->start_addr; //插至末尾 work = free_block; if(work == NULL){ free_block = fbt; fbt->next == NULL; }else{ while(work ->next != NULL){ work = work->next; } fbt->next = work->next; work->next = fbt; } //按地址重新排布 rearrange_FF(); //合并可能分区;即若两空闲分区相连则合并 pre = free_block; while(pre->next){ work = pre->next; if(pre->start_addr + pre->size == work->start_addr ){ pre->size = pre->size + work->size; pre->next = work->next; free(work); continue; }else{ pre = pre->next; } } //按照当前算法排序 rearrange(ma_algorithm); return 1; }
5. 运行结果
根据实验要求,先初始化三个进程,进程所占空间随机生成,之后进入循环,结束释放一个进程,在分配生成一个所占空间大小随机的进程。
测试代码:
int main(int argc, char const *argv[]){ free_block = init_free_block(mem_size); //初始化空闲区 set_mem_size(); int size; srand((unsigned)time(0)); //初始化三个程序 for(int i=0;i<3;i++){ size=rand()%100; create_process(size); } //测试12组数据 for(int j=0;j<12;j++){ int p=j+1; end_process(p);//结束一个 size=rand()%100; create_process(size);//创造一个 display_mem_usage(); } }
结果:
解释:根据之前初始化进程,空间中0到240被分配给进程1、2、3。第一次循环,进程1被释放,即空间0到84被释放。此时,空闲块为0-84和240-1000,较小块为0到84。创建的进程4,随机大小为27,小于84(先拿最小块比较),所以0到27被分配给进程4。所以第一次循环结束后得到图中结果。
解释:第二次循环,进程2被释放,即空间84到174被释放。此时空闲块为27-174和240-1000。生成进程5,随机大小为42,小于空闲块27-174的大小(先拿最小块比较),所以27-69被分配给进程5。此时空闲块为69-174和240-1000,结果如图。
解释:第三次循环,进程3被释放,即空间174到240被释放。此时空闲块为69-240和240-1000,相连合并。生成进程6,随机大小为96,所以69-165被分配给进程6。此时空闲块为165-1000,结果如图。
解释:第四次循环,进程4被释放,即空间0到27被释放。此时空闲块为0-27和165-1000。生成进程7,随机大小为63,因为空间0-27不够放(先拿最小块比较),空间165-1000够放,所以165-228被分配给进程7。此时空闲块为0-27和228-1000,结果如图。