代码改变世界

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

2020-05-17 11:47  Wangpj  阅读(288)  评论(0编辑  收藏  举报

姓名:王丕杰

班级:计算1812

学号:201821121052

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

定义已分配分区的结构体allocated_block,定义一个指针allocated_block_head指向链表表头。

/*记录内存空间使用情况*/
typedef struct allocated_block{
    int pid;
    int size;
    int start_addr;
    char process_name[PNAME_LEN];
    struct allocated_block *next;
}AB;
AB *allocated_block_head = NULL; /*进程分配内存块链表的首指针*/

2. 记录空闲分区

定义空闲分区的结构体free_block_type,定义一个指针free block指向链表表头。

/*记录空闲分区*/
typedef struct free_block_type{
     int size;
     int start_addr;
     struct free_block_type *next;
}FBT;

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

3. 内存分配算法

(1)内存分配算法:首次适配算法

(2)首次适应算法从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。

(3)代码如下:

 void Do_Allocate_Mem(AB *ab){       //分配内存
     int request = ab->size;
     FBT *tmp = free_block;
     while(tmp != NULL){
         if(tmp->size >= request){
             ab->start_addr = tmp->start_addr;
             int residue = tmp->size - request;
             tmp->size = residue;
             tmp->start_addr = tmp->start_addr + request;
             return ;
         }
         tmp = tmp->next;
     }
 }
 int Allocate_Mem(AB *ab){          //分配内存应用
     FBT *fbt,*pre;
     int request_size=ab->size;
     fbt = pre = free_block;
     int f = Find_Free_Mem(request_size); //寻找可分配
     if(f == -1){                         //空闲内存不足
         printf("Not enough free memory!\n");
         return -1;
     }else{
         if(f == 0){                //内存紧缩后分配
             Memory_Compact();
         }
         Do_Allocate_Mem(ab);       //分配
     }
     Rearrange(ma_algorithm);       //重排空闲分区
     return 1;
 }
 int Alloc_Process(PRO prc){        //为进程分配内存
     AB *ab;
     int ret;
     ab = (AB*)malloc(sizeof(AB));
     if(!ab) exit(-5);
     ab->next=NULL;
     pid++;
     strcpy(ab->process_name,prc.process_name);
     ab->pid = pid;
     ab->size=prc.size+rand()%ALLOC_SIZE; //随机分配内存
     ret = Allocate_Mem(ab);              //分配内存,ret==1表示分配成功
     if((ret == 1) && (allocated_block_head == NULL)){ //若allocated_block_head尚未赋值
         allocated_block_head = ab;
         return 1;
     }else if(ret == 1){                  //分配成功
         ab->next = allocated_block_head;
         allocated_block_head = ab;
         return 2;
     }else if(ret == -1){                 //分配不成功
         printf("Fail!\n");
         free(ab);
         return -1;
     }
     return 3;
 }

4. 内存释放算法

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

(2)代码如下:

 int Dispose(AB *free_ab){            //释放链表ab节点
     AB *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(AB *ab){                //更新分区表归还已分配区,以及可能的合并
     int algorithm = ma_algorithm;
     FBT *fbt,*pre,*work;
     fbt = (FBT*)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_FIR();                   //首次适配算法
     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;
 }
 int Kill_Process(int pid){           //释放进程内存
     AB *ab;
     ab = Find_Process(pid);
     if(ab!=NULL){
         Free_Mem(ab);                //释放分配表
         Dispose(ab);                 //释放节点
         return 0;
     }else{
         return -1;
     }
 }

5. 运行结果

(1)产生测试数据

随机为3个进程分配、释放内存10次以上,即随机产生10组以上数据:

     #define PROCESS_NUM 3          //进程数
     int main(int argc, char const *argv[]){
     int sel1,sel2;
     int total=0;                     //记录分配内存的次数
     free_block=Init_Free_Block(mem_size); //初始化空闲区
     PRO prc[PROCESS_NUM];            //存放要加载的进程
     Init_Program(prc,PROCESS_NUM);   //对这几个程进程进行初始化
     srand((unsigned)time(NULL));
     for(int i=0;i<DATA_NUM;++i)
     {
         sel1=rand()%2;
         int count=0;                  //统计三个进程中有多少个进程已经分配内存
         for(int j=0;j<PROCESS_NUM;++j){
             if(prc[j].pid!=-1)
                 count++;
         }        //如果全部分配进程或者进程分配到达10次,那么就不能继续分配内存
         if((count==PROCESS_NUM && sel1==0)||total==10)
             sel1=1;                   //如果全部未分配进程,那么就不能继续释放内存                         
         if(count==0 && sel1==1)
             sel1=0;
         if(sel1==0)                    //为进程分配内存
         {                              //随机找到一个未分配内存的进程                            
             do{
                 sel2=rand()%PROCESS_NUM;
             }while(prc[sel2].pid!=-1);
             Alloc_Process(prc[sel2]);  //分配内存空间                                            
             prc[sel2].pid=pid;         //改变标记
             total++;
             Display_Mem_Usage();       //显示结果                                                         
         }
         else                           //释放进程占用的内存空间                                  
         {
             do{                         //随机找到一个可释放进程                                 
                 sel2=rand()%PROCESS_NUM;
             }while(prc[sel2].pid==-1);                                                           
             Kill_Process(prc[sel2].pid);//释放内存空间
             prc[sel2].pid=-1;           //改变标记                                               
             Display_Mem_Usage();        //显示                                                   
         }                                                                                        
     }    

(2)解释结果

①第一次内存分配:进程名为process-01,起始地址为0,进程占用内存大小为21;剩余空闲分区首地址为21,大小为1003;随后释放进程process-01。

②第二次内存分配:进程名为process-01,起始地址为0,进程占用内存大小为78;剩余空闲分区首地址为78,大小为946;未释放进程process-01。

③第三次内存分配:进程名为process-03,起始地址为78,进程占用内存大小为42;剩余空闲分区首地址为120,大小为904;

释放进程process-01和process-03

④第四次内存分配:进程名为process-02,起始地址为0,进程占用内存大小为93;剩余空闲分区首地址为93,大小为931;释放进程process-02。