模拟linux内存管理代码 转

这个代码模拟实现了linux内存管理的三个算法ff、wf、bf。这三个算法都是连续分配的方式,这种方式的缺点就是内存碎片很难被再次利用。

#include <stdio.h> #include <stdlib.h> #define PROCESS_NAME_LEN 32   /*进程名长度*/ #define MIN_SLICE    10             /*最小碎片的大小*/ #define DEFAULT_MEM_SIZE 1024     /*内存大小*/ #define DEFAULT_MEM_START 0       /*起始位置*/ /* 内存分配算法 */ #define MA_FF 1 #define MA_BF 2 #define MA_WF 3

int mem_size=DEFAULT_MEM_SIZE; /*内存大小*/ int ma_algorithm=MA_FF;           /*当前分配算法*/ static int pid=0;  /*初始pid*/ int flag = 0;/*设置内存大小标志*/ /*描述每一个空闲块的数据结构*/ struct free_block_type{     int size;     int start_addr;     struct free_block_type *next; };

/*指向内存中空闲块链表的首指针*/ struct free_block_type *free_block; /*每个进程分配到的内存块的描述*/ struct allocated_block{     int pid;     int size;//大小     int start_addr;//起始地址    char process_name[PROCESS_NAME_LEN];//进程名字     struct allocated_block *next;     }; /*进程分配内存块链表的首指针*/ struct allocated_block *allocated_block_head = NULL;

void king(struct free_block_type *h)//为有参的函数 { struct free_block_type *p; //对相邻区的处理,和对size==0的处理 if(h->next!=NULL)//感觉这里不对 {  if((h->start_addr+h->size)==h->next->start_addr)  {  p=h->next;  h->size=h->size+p->size;  h->next=p->next;  free(p);  king(h);  } else if(h->next!=NULL) king(h->next); } }

/*连表的销毁*/ void freenode(struct free_block_type *h) {  struct free_block_type *p;  while(h!=NULL)  {p=h;  h=h->next;   free(p);  } } void freenode1(struct allocated_block *h) {  struct allocated_block *p;  while(h!=NULL)  {p=h;  h=h->next;   free(p);  } }

/*初始化空闲块,默认为一块,可以指定大小及起始地址*/ struct free_block_type* init_free_block(int mem_size){     struct free_block_type *fb;

    fb=(struct free_block_type *)malloc(sizeof(struct free_block_type));     if(fb==NULL){         printf("No mem/n");         return NULL;         }     fb->size = mem_size;     fb->start_addr = DEFAULT_MEM_START;     fb->next = NULL;     return fb; }

/*显示菜单*/ void display_menu(){     printf("/n");     printf("1 - Set memory size (default=%d)/n", DEFAULT_MEM_SIZE);     printf("2 - Select memory allocation algorithm/n");     printf("3 - New process /n");     printf("4 - Terminate a process /n");     printf("5 - Display memory usage /n");     printf("0 - Exit/n"); }

/*设置内存的大小*/ int set_mem_size(){     int size;     if(flag!=0){  //防止重复设置         printf("Cannot set memory size again/n");         return 0;         }     printf("Total memory size =");     scanf("%d", &size);     if(size>0) {         mem_size = size;         free_block->size = mem_size;         }     flag=1;  return 1;     }

/*按FF算法重新整理内存空闲块链表*/ void rearrange_FF()//按照地址递增顺序 { struct free_block_type *head,*p,*q,*s,*m,*h; h=free_block; m=free_block; // h=h->next;没有头节点这里为了处理方便,暂且申请头结点 head=(struct free_block_type *)malloc(sizeof(struct free_block_type));  head->next=NULL;  s=head;//保存头结点地址  p=(struct free_block_type *)malloc(sizeof(struct free_block_type));  p->size=h->size;  p->start_addr=h->start_addr;  s->next=p; p->next=NULL;  h=h->next;

 while(h!=NULL)  {   q=(struct free_block_type *)malloc(sizeof(struct free_block_type));   q->size=h->size;   q->start_addr=h->start_addr;   h=h->next;//记录下一个节点   head=s;   p=head->next;   while(head!=NULL)   {    if(head->next==NULL)    {     head->next=q;  q->next=NULL;     break;    }    else if(q->start_addr<p->start_addr)//这里可以修改排序顺序    {     head->next=q;  q->next=p;     break;   }

   else    {head=head->next;    p=head->next;    }   }  }  freenode(m);  m=s;  s=s->next;  free(m);  free_block=s; } /*按BF算法重新整理内存空闲块链表*/ void rearrange_BF()//按照容量从小到大 {     struct free_block_type *head,*p,*q,*s,*m,*h;  h=free_block; m=free_block; // h=h->next;没有头节点这里为了处理方便,暂且申请头结点 head=(struct free_block_type *)malloc(sizeof(struct free_block_type));  head->next=NULL;  s=head;//保存头结点地址  p=(struct free_block_type *)malloc(sizeof(struct free_block_type));  p->size=h->size;  p->start_addr=h->start_addr;  s->next=p; p->next=NULL;  h=h->next;

 while(h!=NULL)  {   q=(struct free_block_type *)malloc(sizeof(struct free_block_type));   q->size=h->size;   q->start_addr=h->start_addr;   h=h->next;//记录下一个节点   head=s;   p=head->next;   while(head!=NULL)   {    if(head->next==NULL)    {     head->next=q;  q->next=NULL;     break;    }    else if(q->size<p->size)//这里可以修改排序顺序    {     head->next=q;  q->next=p;     break;   }

   else    {head=head->next;    p=head->next;    }   }  }  freenode(m);  m=s;  s=s->next;  free(m);  free_block=s; } /*按WF算法重新整理内存空闲块链表*/ void rearrange_WF()//按照容量从大到小 {     struct free_block_type *head,*p,*q,*s,*m,*h;  h=free_block; m=free_block; // h=h->next;没有头节点这里为了处理方便,暂且申请头结点 head=(struct free_block_type *)malloc(sizeof(struct free_block_type));  head->next=NULL;  s=head;//保存头结点地址  p=(struct free_block_type *)malloc(sizeof(struct free_block_type));  p->size=h->size;  p->start_addr=h->start_addr;  s->next=p; p->next=NULL;  h=h->next;

 while(h!=NULL)  {   q=(struct free_block_type *)malloc(sizeof(struct free_block_type));   q->size=h->size;   q->start_addr=h->start_addr;   h=h->next;//记录下一个节点   head=s;   p=head->next;   while(head!=NULL)   {    if(head->next==NULL)    {     head->next=q;  q->next=NULL;     break;    }    else if(q->size>p->size)//这里可以修改排序顺序    {     head->next=q;  q->next=p;     break;   }

   else    {head=head->next;    p=head->next;    }   }  }  freenode(m);  m=s;  s=s->next;  free(m);  free_block=s; }

/*按指定的算法整理内存空闲块链表*/ void rearrange(int algorithm){     switch(algorithm){         case MA_FF:  rearrange_FF(); break;         case MA_BF:  rearrange_BF(); break;         case MA_WF: rearrange_WF(); break;         } }

/* 设置当前的分配算法 */ void set_algorithm(){     int algorithm;     printf("/t1 - First Fit/n");     printf("/t2 - Best Fit /n");     printf("/t3 - Worst Fit /n");     scanf("%d", &algorithm);     if(algorithm>=1 && algorithm <=3)               ma_algorithm=algorithm;     //按指定算法重新排列空闲区链表     rearrange(ma_algorithm); } /*分配内存模块*/ int allocate_mem(struct allocated_block *ab) {

    struct free_block_type  *h;     int request_size=ab->size;  rearrange(ma_algorithm);//这里虽然能够排序,但是地址发生了变化   h=free_block; while(h!=NULL) {  if(h->size>=request_size)   break;  h=h->next; } if(h==NULL) {  printf("不符合分配条件");  return -1; } else {  printf("符合分配条件");  if(h->size-request_size<MIN_SLICE)          h->size=0;//注意这里只是修改了链表中值的大小,链表的本体还在  else   h->size=h->size-request_size;    ab->start_addr=h->start_addr;    h->start_addr=ab->start_addr+ab->size;  return 1; }

}

struct allocated_block *find_process(int p) {  struct allocated_block *h;  h=allocated_block_head; while(h!=NULL) {  if(h->pid==p)   break;  else   h=h->next; } return h; }

/*删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点*/ void kill_process(){     struct allocated_block *ab;     int p;//这里的pid和全局变量的pid怎么说     printf("Kill Process, pid=");     scanf("%d", &p);     ab=find_process(p);//注意这个函数,可能是遗漏     if(ab!=NULL){         free_mem(ab); /*释放ab所表示的分配区*/         dispose(ab);  /*释放ab数据结构节点*/         } } /*将ab所表示的已分配区归还,并进行可能的合并*/ int free_mem(struct allocated_block *ab){     int algorithm = ma_algorithm;//算法     struct free_block_type *h,*fbt;  h=free_block;   fbt=(struct free_block_type*) malloc(sizeof(struct free_block_type));     fbt->size=ab->size;  fbt->start_addr=ab->start_addr;

    // 进行可能的合并,基本策略如下     // 1. 将新释放的结点插入到空闲分区队列末尾     // 2. 对空闲链表按照地址有序排列     // 3. 检查并合并相邻的空闲分区     // 4. 将空闲链表重新按照当前算法排序    // 请自行补充…… while(h->next!=NULL) h=h->next; h->next=fbt; fbt->next=NULL; rearrange_FF();//2 king(free_block);//3 rearrange(ma_algorithm);//4  return 1; } /*创建新的进程,主要是获取内存的申请数量*/ int new_process(){     struct allocated_block *ab;     int size;     int ret;     ab=(struct allocated_block *)malloc(sizeof(struct allocated_block));     if(!ab) exit(-5);     ab->next = NULL;     pid++;     sprintf(ab->process_name, "PROCESS-%02d", pid);     ab->pid = pid;     printf("Memory for %s:", ab->process_name);     scanf("%d", &size);     if(size>0) ab->size=size;     ret = allocate_mem(ab);  /* 从空闲区分配内存,ret==1表示分配ok*/   /*如果此时allocated_block_head尚未赋值,则赋值*/     if((ret==1) &&(allocated_block_head == NULL)){         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("Allocation fail/n");         free(ab);         return -1;      }     return 3;     }

/*释放ab数据结构节点*/ int dispose(struct allocated_block *free_ab){     struct allocated_block *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;    }

/* 显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 */ display_mem_usage(){     struct free_block_type *fbt=free_block;     struct allocated_block *ab=allocated_block_head;     if(fbt==NULL) return(-1);     printf("----------------------------------------------------------/n");

    /* 显示空闲区 */     printf("Free Memory:/n");     printf("%20s %20s/n", "      start_addr", "       size");     while(fbt!=NULL){   if(fbt->size==0)   {    fbt=fbt->next;    continue;   }         printf("%20d %20d/n", fbt->start_addr, fbt->size);         fbt=fbt->next;         }  /* 显示已分配区 */     printf("/nUsed Memory:/n");     printf("%10s %20s %10s %10s/n", "PID", "ProcessName", "start_addr", " size");     while(ab!=NULL){         printf("%10d %20s %10d %10d/n", ab->pid, ab->process_name, ab->start_addr, ab->size);         ab=ab->next;         }     printf("----------------------------------------------------------/n");     return 0;     }

int main(){     char choice;      pid=0;     free_block = init_free_block(mem_size); //初始化空闲区     while(1)  {     display_menu();    //显示菜单     fflush(stdin);//这里的这个函数,linux下可以用其他的代替     choice=getchar();    //获取用户输入     switch(choice){         case '1': set_mem_size(); break;     //设置内存大小         case '2': set_algorithm();flag=1; break;//设置算法         case '3': new_process(); flag=1; break;//创建新进程         case '4': kill_process(); flag=1;   break;//删除进程         case '5': display_mem_usage();    flag=1; break;    //显示内存使用         case '0': freenode(free_block);freenode1(allocated_block_head); exit(0);    //释放链表并退出         default: break;      }    }  return 0; }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏行者悟空

Hadoop之MapReduce原理及运行机制

21140
来自专栏技术点滴

单例模式(Singleton)

单例模式(Singleton) 单例模式(Singleton) 意图:保证一个类只有一个实例,并提供一个访问它的全局访问点。 应用:Session或者控件的唯一...

19660
来自专栏听雨堂

Python防止sql注入

看了网上文章,说的都挺好的,给cursor.execute传递格式串和参数,就能防止注入,但是我写了代码,却死活跑不通,怀疑自己用了一个假的python 最后,...

38770
来自专栏运维咖啡吧

Django model select的各种用法详解

Q对象可以对关键字参数进行封装,从而更好的应用多个查询,可以组合&(and)、|(or)、~(not)操作符。

11730
来自专栏用户画像

JAVA单例模式

在整个应用中,保证一个类只有一个实例,它提供了一个可以访问到它自己的全局访问点(静态方法)。

11220
来自专栏chenssy

【死磕Java并发】—–Java内存模型之从JMM角度分析DCL

DCL,即Double Check Lock,中卫双重检查锁定。其实DCL很多人在单例模式中用过,LZ面试人的时候也要他们写过,但是有很多人都会写错。他们为什么...

416110
来自专栏专注 Java 基础分享

初识Hibernate之关联映射(一)

     上篇文章我们对持久化对象进行的学习,了解了它的三种不同的状态并通过它完成对数据库的映射操作。但这都是基于单张表的操作,如果两张或者两张以上的表之间存在...

19380
来自专栏菩提树下的杨过

温故而知新:设计模式之单件模式(Singleton)

 1 using System;  2  3 namespace Singleton  4 {  5 class Program  6     {  7 ...

19270
来自专栏chenssy

【死磕Java并发】-----Java内存模型之从JMM角度分析DCL

DCL,即Double Check Lock,即双重检查锁定。其实DCL很多人在单例模式中用过,LZ面试人的时候也要他们写过,但是有很多人都会写错。他们为什么会...

13430
来自专栏别先生

一脸懵逼学习oracle

oracle的默认用户:system,sys,scott; 1:查看登录的用户名:show user; 2:查看数据字典:dba_users; 3:创建新...

18970

扫码关注云+社区

领取腾讯云代金券