不考虑性能的内存管理模拟系统(假内存)的C语言实现
#include<stdio.h> /*头文件*/
#define PROCESS_NAME_LEN 32 /*进程名长度*/
#define MIN_SLICE 10 /*最小碎片的大小*/
#define DEFAULT_MEM_SIZE 1024 /*内存大小*/
#define DEFAULT_MEM_START 0 /*起始位置*/
#define FF 1 /*首次适应*/
#define BF 2 /*最佳适应*/
#define WF 3 /*最坏适应*/
int mem_size = DEFAULT_MEM_SIZE; /*内存大小*/
int manage_algorithm = FF; /*当前分配算法*/
static int pid = 0; /*初始pid*/
int flag = 0; /*内存是否已设置标志*/
/*********************************************************/
typedef struct free_block{ /*描述每一个空闲块的数据结构*/
int size; /*空闲块大小*/
int start_addr; /*起始地址*/
struct free_block* next; /*下一个空闲块的指针*/
}free_block;
free_block* head_of_free_block = NULL; //指向内存中空闲块链表的首指针
/*********************************************************/
typedef struct allocated_block{ /*进程已分配的内存块的描述*/
int pid; /*所占进程的标识符*/
int size; /*块大小*/
int start_addr; /*起始地址*/
char process_name[PROCESS_NAME_LEN]; /*进程名*/
struct allocated_block *next; /*下一个分配快*/
}allocated_block;
allocated_block* head_of_allocated_block = NULL; /*进程分配内存块链表的首指针*/
/*********************************************************/
free_block* init_free_block(int); //初始化空闲区
void display_menu(void); //显示菜单
int set_mem_size(void); //设置内存大小
void set_algorithm(void); //设置算法
void rearrange(int); //重排链表
void rearrange_FF(void); //首次重排
void rearrange_BF(void); //最佳重排
void rearrange_WF(void); //最坏重排
int new_process(void); //创建新进程
int allocate_mem(allocated_block*); //分配内存
void rearrange_Allocated(void); //进程链排序
void kill_process(void); //删除进程
allocated_block* find_process(int pid); //查找块位置
int dispose(allocated_block*); //块归还
int free_mem(allocated_block*); //释放内存
int display_mem_usage(void); //显示内存使用
void do_exit(void); //释放链表并退出
/*********************************************************/
int main(void){
char choice; /*选择的功能*/
pid = 0; /*初始化pid*/
head_of_free_block = init_free_block(mem_size); //初始化空闲区
while(1){
display_menu(); //显示菜单
fflush(stdin);
choice = getchar(); //获取用户输入
switch(choice){
case '1':set_mem_size();break; //设置内存大小
case '2':set_algorithm();break;//设置算法
case '3':new_process();break;//创建新进程
case '4':kill_process();break;//删除进程
case '5':display_mem_usage();break; //显示内存使用
case '0':do_exit();exit(0); //释放链表并退出
default:printf("ErrorInput_Exception\n");break;
}
}
}
/*********************************************************/
/*初始化空闲块,默认为一块,可以指定大小及起始地址*/
free_block* init_free_block(int mem_size){
free_block* fb = NULL;
fb = (free_block*)malloc(sizeof(free_block));
if(fb==NULL){
printf("MemoryOverFlow_Exception\n");
return NULL;
}
fb->size = mem_size;
fb->start_addr = DEFAULT_MEM_START;
fb->next = NULL;
return fb;
}
/*********************************************************/
/*显示菜单*/
void display_menu(void){
printf("\n");
printf("1 - Set memory size (default=%d,current=%d)\n",DEFAULT_MEM_SIZE,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(void){
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;
head_of_free_block->size = mem_size;
flag = 1;
}
else printf("SizeSetNoLegal_Exception\n");
return 1;
}
/*********************************************************/
/* 设置当前的分配算法 */
void set_algorithm(void){
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)
manage_algorithm = algorithm;
else{
printf("NoSuchAlgorithm_Exception\n");
return -1;
}
flag = 1;
rearrange(manage_algorithm); //按指定算法重新排列空闲区链表
}
/*********************************************************/
/*按指定的算法整理内存空闲块链表*/
void rearrange(int algorithm){
switch(algorithm){
case FF:rearrange_FF();break;
case BF:rearrange_BF();break;
case WF:rearrange_WF();break;
}
}
/*********************************************************/
/*按FF算法重新整理内存空闲块链表*/
void rearrange_FF(void){
free_block* fb; //内循环
free_block* temp; //外循环
int size;
int start_addr;
for(temp = head_of_free_block;temp != NULL;temp = temp->next){
for(fb = temp->next;fb != NULL;fb = fb->next){
if(temp->start_addr > fb->start_addr){
size = temp->size;
start_addr = temp->start_addr;
temp->size = fb->size;
temp->start_addr = fb->start_addr;
fb->size = size;
fb->start_addr = start_addr;
}
}
}
}
/*********************************************************/
/*按BF算法重新整理内存空闲块链表*/
void rearrange_BF(void){
free_block* fb; //内循环
free_block* temp; //外循环
int size;
int start_addr;
for(temp = head_of_free_block;temp != NULL;temp = temp->next){
for(fb = temp->next;fb != NULL;fb = fb->next){
if(temp->size > fb->size){
size = temp->size;
start_addr = temp->start_addr;
temp->size = fb->size;
temp->start_addr = fb->start_addr;
fb->size = size;
fb->start_addr = start_addr;
}
}
}
}
/*********************************************************/
/*按WF算法重新整理内存空闲块链表*/
void rearrange_WF(void){
free_block* fb; //内循环
free_block* temp; //外循环
int size;
int start_addr;
for(temp = head_of_free_block;temp != NULL;temp = temp->next){
for(fb = temp->next;fb != NULL;fb = fb->next){
if(temp->size < fb->size){
size = temp->size;
start_addr = temp->start_addr;
temp->size = fb->size;
temp->start_addr = fb->start_addr;
fb->size = size;
fb->start_addr = start_addr;
}
}
}
}
/*********************************************************/
/*创建新的进程,主要是获取内存的申请数量*/
int new_process(void){
allocated_block* ab;
int size;
ab=(allocated_block*)malloc(sizeof(allocated_block));
if(!ab) exit(-5);
ab->next = NULL;
pid++;
sprintf(ab->process_name, "PROCESS-%02d\0", pid);
ab->pid = pid;
printf("Memory for %s:", ab->process_name);
scanf("%d", &size);
if(size>0) ab->size = size;
else{
printf("SizeNotLegal_Exception\n");
pid--;
return -1;
}
ab->start_addr = allocate_mem(ab); /* 从空闲区分配内存,ab->start_addr表示分配地址,-1表示未成功*/
if((ab->start_addr != -1) && (head_of_allocated_block == NULL)){ /*如果此时head_of_allocated_block尚未赋值,则赋值*/
head_of_allocated_block = ab;
flag = 1;
return 1;
}
else if (ab->start_addr != -1){ /*分配成功,将该已分配块的描述插入已分配链表,头插法*/
ab->next = head_of_allocated_block;
head_of_allocated_block = ab;
flag = 1;
return 2;
}
else if(ab->start_addr == -1){ /*分配不成功*/
printf("AllocationFail_Exception\n");
free(ab);
return -2;
}
return 3;
}
/*********************************************************/
/*分配内存模块*/
int allocate_mem(allocated_block* ab){
free_block *now, *pre;
int request_size = ab->size;
now = pre = head_of_free_block;
double temp;
int sum_size = 0;
// 1. 找到可满足空闲分区且分配后剩余空间足够大,则分割
// 2. 找到可满足空闲分区且但分配后剩余空间比较小,则一起分配
// 3. 找不可满足需要的空闲分区但空闲分区之和能满足需要,则采用内存紧缩技术,进行空闲分区的合并,然后再分配
// 4. 在成功分配内存后,应保持空闲分区按照相应算法有序
// 5. 分配成功则返回分配首地址,否则返回-1
while(now != NULL){
sum_size = sum_size + now->size;
if(request_size <= now->size){
temp = (double)(now->size-request_size)/(double)now->size;
if(temp <= 0.1){ //剩余空间小于百分之十
int addr = now->start_addr;
if(head_of_free_block->next == NULL){
ab->size = head_of_free_block->size;
head_of_free_block = NULL;
}
else{
if(now == head_of_free_block){
ab->size = head_of_free_block->size;
head_of_free_block = head_of_free_block->next;
}
else{
ab->size = now->size;
pre->next = now->next;
}
}
return addr;
}
else{ //剩余空间大于百分之十
int addr = now->start_addr; //分配
now->start_addr = now->start_addr + request_size;
now->size = now->size - request_size; //减少内存
switch(manage_algorithm){ //管理重排
case FF:rearrange_FF();break;
case BF:rearrange_BF();break;
case WF:rearrange_WF();break;
}
return addr;
}
}
pre = now;
now = now->next;
}
if(sum_size < request_size) return -1;
else{ //内存紧缩技术
rearrange_Allocated(); //进程链排序
allocated_block* abt = head_of_allocated_block;
int size_T = 0;
while(abt != NULL){
abt->start_addr = size_T;
size_T = size_T + abt->size;
abt = abt->next;
}
free_block* fbt;
while(head_of_free_block->next != NULL){ //空闲链合并
fbt = head_of_free_block;
head_of_free_block = head_of_free_block->next;
free(fbt);
}
head_of_free_block->start_addr = size_T;
head_of_free_block->size = sum_size;
//分配
int addr = head_of_free_block->start_addr; //分配
head_of_free_block->start_addr = head_of_free_block->start_addr + request_size;
head_of_free_block->size = head_of_free_block->size - request_size; //减少内存
return addr;
}
return 0;
}
/*********************************************************/
/*对进程链地址排序*/
void rearrange_Allocated(void){
allocated_block* ab; //内循环
allocated_block* temp; //外循环
int pid;
int size;
int start_addr;
char process_name[PROCESS_NAME_LEN];
for(temp = head_of_allocated_block;temp != NULL;temp = temp->next){
for(ab = temp->next;ab != NULL;ab = ab->next){
if(temp->start_addr > ab->start_addr){
pid = temp->pid;
size = temp->size;
start_addr = temp->start_addr;
strcpy(process_name,temp->process_name);
temp->pid = ab->pid;
temp->size = ab->size;
temp->start_addr = ab->start_addr;
strcpy(temp->process_name,ab->process_name);
ab->pid = pid;
ab->size = size;
ab->start_addr = start_addr;
strcpy(ab->process_name,process_name);
}
}
}
}
/*********************************************************/
/*删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点*/
void kill_process(void){
allocated_block* ab;
int pid;
printf("Kill Process, pid=");
scanf("%d", &pid);
ab = find_process(pid);
if(ab != NULL){
flag = 1;
free_mem(ab); /*释放ab所表示的分配区*/
dispose(ab); /*释放ab数据结构节点*/
}
else printf("NoSuchProcess_Exception\n");
}
/*********************************************************/
/*查找pid进程所在块*/
allocated_block* find_process(int pid){
allocated_block* ab = head_of_allocated_block;
while(ab != NULL){
if(ab->pid == pid) break;
ab = ab->next;
}
return ab;
}
/*********************************************************/
/*将ab所表示的已分配区归还,并进行可能的合并*/
int free_mem(allocated_block* ab){
int algorithm = manage_algorithm;
free_block *fb, *pre, *now;
fb = (free_block*)malloc(sizeof(free_block));
if(!fb) return -1;
fb->size = ab->size;
fb->start_addr = ab->start_addr;
fb->next = NULL;
// 1. 将新释放的结点插入到空闲分区队列末尾
// 2. 对空闲链表按照地址有序排列
// 3. 检查并合并相邻的空闲分区
// 4. 将空闲链表重新按照当前算法排序
if(head_of_free_block == NULL) head_of_free_block = fb;
else{
now = head_of_free_block;
while(now->next != NULL) now = now->next;
now->next = fb;
rearrange_FF();
pre = head_of_free_block;
now = head_of_free_block->next;
while(now != NULL){
if((pre->start_addr + pre->size) == now->start_addr){
fb = now;
pre->size = pre->size + now->size;
pre->next = now->next;
free(fb);
now = pre->next;
}
else{
pre = now;
now = now->next;
}
}
switch(algorithm){ //管理重排
case FF:rearrange_FF();break;
case BF:rearrange_BF();break;
case WF:rearrange_WF();break;
}
}
return 1;
}
/*********************************************************/
/*释放ab数据结构节点*/
int dispose(allocated_block* free_ab){
allocated_block *pre, *ab;
if(free_ab == head_of_allocated_block){ /*如果要释放第一个节点*/
head_of_allocated_block = head_of_allocated_block->next;
free(free_ab);
return 1;
}
pre = head_of_allocated_block;
ab = head_of_allocated_block->next;
while(ab != free_ab){
pre = ab;
ab = ab->next;
}
pre->next = ab->next;
free(ab);
return 2;
}
/*********************************************************/
/* 显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 */
int display_mem_usage(void){
free_block* fbt = head_of_free_block;
allocated_block* ab = head_of_allocated_block;
printf("----------------------------------------------------------\n");
/* 显示空闲区 */
printf("Free Memory:\n");
printf("%20s %20s\n", " start_addr", " size");
if(fbt == NULL)
printf("%20d %20d\n", -1, 0);
else{
while(fbt != NULL){
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");
flag = 1;
return 0;
}
/*********************************************************/
/* 结束前的内存回收 */
void do_exit(void){
free_block* fb = NULL;
allocated_block* ab = NULL;
while(head_of_free_block != NULL){
fb = head_of_free_block;
head_of_free_block = head_of_free_block->next;
free(fb);
}
while(head_of_allocated_block != NULL){
ab = head_of_allocated_block;
head_of_allocated_block = head_of_allocated_block->next;
free(ab);
}
}