操作系统第5次实验报告:内存管理
- 姓名:程开
- 学号:201821121060
- 班级:计算1812
1. 记录内存空间使用情况
pid记录进程号,size记录大小,start_addr记录起始地址,process_name记录进程名
*next记录下一个内存块
2. 记录空闲分区
同上
3. 内存分配算法
1 //执行分配内存 2 void do_allocate_mem(AB *ab){ 3 int request = ab->size; 4 FBT *tmp = free_block; 5 while(tmp != NULL){ 6 if(tmp->size >= request){ 7 //分配 8 ab->start_addr = tmp->start_addr; 9 int shengyu = tmp->size - request; 10 tmp->size = shengyu; 11 tmp->start_addr = tmp->start_addr + request; 12 13 return ; 14 } 15 tmp = tmp->next; 16 } 17 } 18 19 int allocate_mem(AB *ab){ 20 /*分配内存模块*/ 21 FBT *fbt,*pre; 22 int request_size=ab->size; 23 fbt = pre = free_block; 24 //尝试寻找可分配空闲,具体结果在函数中有解释 25 int f = find_free_mem(request_size); 26 if(f == -1){ 27 //不够分配 28 printf("空闲内存不足,内存分配失败!\n"); 29 return -1; 30 }else{ 31 if(f == 0){ 32 //需要内存紧缩才能分配 33 memory_compact(); 34 } 35 //执行分配 36 do_allocate_mem(ab); 37 } 38 //重新排布空闲分区 39 rearrange(ma_algorithm); 40 return 1; 41 } 42 43 //为进程分配内存 44 int alloc_process(Prc prc){ 45 AB *ab; 46 int ret; 47 ab = (AB*)malloc(sizeof(AB)); 48 if(!ab) exit(-5); 49 /*为ab赋值 */ 50 ab->next=NULL; 51 pid++;//记录id 52 strcpy(ab->process_name,prc.process_name); 53 ab->pid = pid; 54 ab->size=prc.size+rand()%ALLOC_SIZE;//随机分配内存 55 56 ret = allocate_mem(ab); //从空闲分区分配内存,ret==1表示分配成功 57 if((ret == 1) && (allocated_block_head == NULL)){ 58 /*如果此时allocated_block_head尚未赋值,则赋值*/ 59 allocated_block_head = ab; 60 return 1; 61 }else if(ret == 1){ 62 /*分配成功,将该分配块的描述插入已分配链表*/ 63 ab->next = allocated_block_head; 64 allocated_block_head = ab; 65 return 2; 66 }else if(ret == -1){ 67 //分配不成功 68 printf("\e[0;31;1m 内存分配失败! \e[0m\n"); 69 free(ab); 70 return -1; 71 } 72 return 3; 73 }
- 使用首次适配算法
- 从最低地址的空闲分区开始找起,找到合适的便进行分配,内存空间按起始地址从小到大排序
- 优点是查找速度快,缺点是内存碎片多
4. 内存释放算法
1 //初始化空闲分区链表 2 FBT *init_free_block(int mem_size){ 3 FBT *fb; 4 5 fb = (FBT*)malloc(sizeof(FBT)); 6 if(fb==NULL){ 7 printf("No mem\n"); 8 return NULL; 9 } 10 fb->size = mem_size; 11 fb->start_addr = DEFAULT_MEM_START; 12 fb->next = NULL; 13 return fb; 14 } 15 //释放链表节点 16 int dispose(AB *free_ab){ 17 /*释放ab数据结构节点*/ 18 AB *pre,*ab; 19 if(free_ab == allocated_block_head){ 20 //如果要是释放第一个节点 21 allocated_block_head = allocated_block_head->next; 22 free(free_ab); 23 return 1; 24 } 25 pre = allocated_block_head; 26 ab = allocated_block_head->next; 27 while(ab!=free_ab){ 28 pre = ab; 29 ab = ab->next; 30 } 31 pre->next = ab->next; 32 free(ab); 33 return 2; 34 } 35 36 //更新分区表 37 int free_mem(AB *ab){ 38 /* 将ab所表示的已分配区归还,并进行可能的合并 */ 39 int algorithm = ma_algorithm; 40 FBT *fbt,*pre,*work; 41 fbt = (FBT*)malloc(sizeof(FBT)); 42 if(!fbt) return -1; 43 fbt->size = ab->size; 44 fbt->start_addr = ab->start_addr; 45 46 //插至末尾 47 work = free_block; 48 if(work == NULL){ 49 free_block = fbt; 50 fbt->next == NULL; 51 }else{ 52 while(work ->next != NULL){ 53 work = work->next; 54 } 55 fbt->next = work->next; 56 work->next = fbt; 57 } 58 //按地址重新排布 59 rearrange_FF(); 60 61 //合并可能分区;即若两空闲分区相连则合并 62 pre = free_block; 63 while(pre->next){ 64 work = pre->next; 65 if(pre->start_addr + pre->size == work->start_addr ){ 66 pre->size = pre->size + work->size; 67 pre->next = work->next; 68 free(work); 69 continue; 70 }else{ 71 pre = pre->next; 72 } 73 } 74 75 //按照当前算法排序 76 rearrange(ma_algorithm); 77 return 1; 78 } 79 80 //找到pid对应的链表节点 81 AB *find_process(int pid){ 82 AB *tmp = allocated_block_head; 83 while(tmp != NULL){ 84 if(tmp->pid == pid){ 85 return tmp; 86 } 87 tmp = tmp->next; 88 } 89 printf("\e[0;31;1m 没有找到进程id为%d的进程! \e[0m\n",pid); 90 return NULL; 91 } 92 93 int kill_process(int pid){ 94 AB *ab; 95 ab = find_process(pid); 96 if(ab!=NULL){ 97 free_mem(ab); //释放ab所表示的分配表 98 dispose(ab); //释放ab数据结构节点 99 return 0; 100 }else{ 101 return -1; 102 } 103 }
- 找到对应的链表节点,释放内存块
5. 运行结果
测试代码
1 int main(int argc, char const *argv[]){ 2 int sel1,sel2; 3 int total=0; //记录分配内存的次数 4 free_block = init_free_block(mem_size);//初始化空闲区 5 Prc prc[PROCESS_NUM];//存放要加载的进程 6 init_program(prc,PROCESS_NUM);//对这几个程进程进行初始化 7 srand((unsigned)time(NULL)); 8 for(int i=0;i<DATA_NUM;++i) 9 { 10 /* 11 sel1=0表示为某进程分配内存空间 12 sel1=1表示为释放某进程占用的内存空间 13 */ 14 sel1=rand()%2; 15 int count=0; 16 //统计三个进程中有多少个进程已经分配内存 17 for(int j=0;j<PROCESS_NUM;++j){ 18 if(prc[j].pid!=-1) 19 count++; 20 } 21 //如果全部分配进程或者进程分配到达5次,那么就不能继续分配内存改为释放内存 22 if((count==PROCESS_NUM && sel1==0)||total==5) 23 sel1=1; 24 //如果全部未分配进程,那么就不能继续释放内存 25 if(count==0 && sel1==1) 26 sel1=0; 27 if(sel1==0)//为进程分配内存 28 { 29 //随机找到一个未分配内存的进程 30 do{ 31 sel2=rand()%PROCESS_NUM; 32 }while(prc[sel2].pid!=-1); 33 alloc_process(prc[sel2]);//分配内存空间 34 prc[sel2].pid=pid;//改变标记 35 total++; 36 display_mem_usage();//显示 37 } 38 else//释放进程占用的内存空间 39 { 40 //随机找到一个可释放进程 41 do{ 42 sel2=rand()%PROCESS_NUM; 43 }while(prc[sel2].pid==-1); 44 kill_process(prc[sel2].pid);//释放内存空间 45 prc[sel2].pid=-1;//改变标记 46 display_mem_usage();//显示 47 } 48 } 49 }
进程1 process-02起始地址0,大小82,进程2 process-01起始地址82,大小85, 随后释放进程
进程3 process-03起始地址0,大小65
进程4 process-01起始地址65,大小74
进程5 process-02起始地址65+74=139,大小44
然后剩余空闲的内存起始地址139+44=183,大小841