操作系统第5次实验报告:内存管理

姓名:蔡婷婷   学号:201821121003    班级:计算1811

1. 记录内存空间使用情况

①解释你是如何记录内存空间使用情况

建立一个链表来记录内存空间的使用情况,定义结构体allocated_block来存放加载至内存中的进程,定义一个指针allocated_block_head指向链表表头,对进程分配内存空间时,就将分配到内存空间的进程块节点添加到链表中;对进程内存进行释放时,就将成功释放的进程块节点从链表中删除。

②给出关键代码

 23 typedef struct allocated_block{

 24     int pid;

 25     int size;

 26     int start_addr;

 27     char process_name[NAME_LEN];

 28     struct allocated_block *next;

 29 }AB;

 42 AB *allocated_block_head = NULL;

2. 记录空闲分区

①用什么样的方法记录内存空闲区

定义空闲分区的结构体free_block_type,定义一个指针free block指向链表表头,对内存初始化后,空闲分区按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。

②给出关键代码

 16 typedef struct free_block_type{

 17     int size;

 18     int start_addr;

 19     struct free_block_type *next;

 20 }FBT;

 39 FBT *free_block;//指向内存中空闲块链表的首指针

3. 内存分配算法

①使用什么样的内存分配算法,并解释

内存分配:首次适配

先在在空闲分区链表中搜索合适空闲分区进行分配,分配时如果找到可满足空闲分区且分配后剩余空间足够大,则分割;如果找不可满足需要的空闲分区但空闲分区之和能满足需要,则采用内存紧缩技术,进行空闲分区的合并,然后再分配。

②给出算法源代码

331 void do_allocate_mem(AB *ab){

332     int request = ab->size;

333     FBT *tmp = free_block;

334     while(tmp != NULL){

335         if(tmp->size >= request){

336             //分配

337             ab->start_addr = tmp->start_addr;

338             int shengyu = tmp->size - request;

339             tmp->size = shengyu;

340             tmp->start_addr = tmp->start_addr + request;

341

342             return ;

343         }

344         tmp = tmp->next;

345     }

346 }

347

348 int allocate_mem(AB *ab){

349     /*分配内存模块*/

350     FBT *fbt,*pre;

351     int request_size=ab->size;

352     fbt = pre = free_block;

353     //尝试寻找可分配空闲,具体结果在函数中有解释

354     int f = find_free_mem(request_size);

355     if(f == -1){

356         //不够分配

357         printf("空闲内存不足,内存分配失败!\n");

358         return -1;

359     }else{

360         if(f == 0){

361             //需要内存紧缩才能分配

362             memory_compact();

363         }

364         //执行分配

365         do_allocate_mem(ab);

366     }

367     //重新排布空闲分区

368     rearrange(ma_algorithm);

369     return 1;

370 }

404 void rearrange_FF(){

405     /*首次适应算法,空闲区大小按起始地址升序排序*/

406     //这里使用冒泡排序方法

407     if(free_block == NULL || free_block->next == NULL)

408         return;

409     FBT *t1,*t2,*head;

410     head = free_block;

411     for(t1 = head->next;t1;t1 = t1->next){

412         for(t2 = head;t2 != t1;t2=t2->next){

413             if(t2->start_addr > t2->next->start_addr){

414                 int tmp = t2->start_addr;

415                 t2->start_addr = t2->next->start_addr;

416                 t2->next->start_addr = tmp;

417

418                 tmp = t2->size;

419                 t2->size = t2->next->size;

420                 t2->next->size = tmp;

421             }

422         }

423     }

424 }

4. 内存释放算法

①进程终止,释放内存,如何释放,如何更新内存空闲分区表。

释放:找到对应的链表节点,释放杀死进程的内存块,归还进程的已分配的存储空间,按从小到大排序,销毁杀死进程的结点。

更新:将新释放的结点插入到空闲分区队列末尾,对空闲链表按照地址有序排列,检查并合并相邻的空闲分区,将空闲链表重新按照首次适配算法排序

②给出算法源代码

152 int dispose(AB *free_ab){

153     /*释放ab数据结构节点*/

154     AB *pre,*ab;

155     if(free_ab == allocated_block_head){

156         //如果要是释放第一个节点

157         allocated_block_head = allocated_block_head->next;

158         free(free_ab);

159         return 1;

160     }

161     pre = allocated_block_head;

162     ab = allocated_block_head->next;

163     while(ab!=free_ab){

164         pre = ab;

165         ab = ab->next;

166     }

167     pre->next = ab->next;

168     free(ab);

169     return 2;

170 }

171

172 //更新分区表

173 int free_mem(AB *ab){

174     // ab所表示的已分配区归还,并进行可能的合并

175     int algorithm = ma_algorithm;

176     FBT *fbt,*pre,*work;

177     fbt = (FBT*)malloc(sizeof(FBT));

178     if(!fbt) return -1;

179     fbt->size = ab->size;

180     fbt->start_addr = ab->start_addr;

181     //插至末尾

182     work = free_block;

183     if(work == NULL){

184         free_block = fbt;

185         fbt->next == NULL;

186     }else{

187         while(work ->next != NULL){

188             work = work->next;

189         }

190         fbt->next = work->next;

191         work->next = fbt;

192     }

193     //按地址重新排布

194     rearrange_FF();

195     //合并可能分区;即若两空闲分区相连则合并

196     pre = free_block;

197     while(pre->next){

198         work = pre->next;

199         if(pre->start_addr + pre->size == work->start_addr ){

200             pre->size = pre->size + work->size;

201             pre->next = work->next;

202             free(work);

203             continue;

204         }else{

205             pre = pre->next;

206         }

207     }

208     //按照当前算法排序

209     rearrange(ma_algorithm);

210     return 1;

211 }

226 int kill_process(int pid){

227     AB *ab;

228     ab = find_process(pid);

229     if(ab!=NULL){

230         free_mem(ab);   //释放ab所表示的分配表

231         dispose(ab);    //释放ab数据结构节点

232         return 0;

233     }else{

234         return -1;

235     }

236 }

5. 运行结果

1)产生测试数据

随机为3个进程分配、释放内存10次以上,即随机产生10组以上数据:(进程Pi 分配内存大小) 或者 (进程Pi结束)

①代码

 61 int main(int argc, char const *argv[]){

 62     /* code */

 63     int sel1,sel2;

 64     int total=0; //记录分配内存的次数

 65     free_block = init_free_block(mem_size); //初始化空闲区

 66

 67     Prc prc[PROCESS_NUM];//存放要加载的进程

 68     init_program(prc,PROCESS_NUM);//对这几个程进程进行初始化

 69     srand( (unsigned)time( NULL ) );

 70

 71     for(int i=0;i<DATA_NUM;++i)

 72     {

 73         sel1=rand()%2;

 74         int count=0;

 75         //统计三个进程中有多少个进程已经分配内存

 76         for(int j=0;j<PROCESS_NUM;++j){

 77             if(prc[j].pid!=-1)

 78                 count++;

 79         }

 80         //如果全部分配进程或者进程分配到达10次,那么就不能继续分配内存

 81         if((count==PROCESS_NUM && sel1==0)||total==10)

 82             sel1=1;

 83         //如果全部未分配进程,那么就不能继续释放内存

 84         if(count==0 && sel1==1)

 85             sel1=0;

 86         if(sel1==0)//为进程分配内存

 87         {

 88             //随机找到一个未分配内存的进程

 89             do{

 90                 sel2=rand()%PROCESS_NUM;

 91             }while(prc[sel2].pid!=-1);

 92             alloc_process(prc[sel2]);//分配内存空间

 93             prc[sel2].pid=pid;//改变标记

 94             total++;

 95             display_mem_usage();//显示

 96         }

 97         else//释放进程占用的内存空间

 98         {

 99             //随机找到一个可释放进程

100             do{

101                 sel2=rand()%PROCESS_NUM;

102             }while(prc[sel2].pid==-1);

103             kill_process(prc[sel2].pid);//释放内存空间

104             prc[sel2].pid=-1;//改变标记

105             display_mem_usage();//显示

106         }

107     }

108 }

②运行结果

 

 

 

(2)解释结果

分析前4组结果

①第一次组为进程process-01分配了从0开始,大小为56的一块内存单元,分配后空闲分区内存剩余地址从56开始,大小为968。

 

②第二次组为进程process-03分配了从56开始,大小为81的一块内存单元,分配后空闲分区内存剩余地址从137开始,大小为887。

 

③第三次组释放进程process-03从56开始大小为81的一块内存单元,分配后空闲分区内存剩余地址从56开始,大小为968。

 

④第四次组为进程process-03分配了从56开始,大小为78的一块内存单元,分配后空闲分区内存剩余地址从132开始,大小为892。

 

posted @ 2020-05-16 20:30  TsoiTing  阅读(306)  评论(0编辑  收藏  举报