动态异长分区内存分配与去配算法的设计-最差适应算法

动态异长分区内存分配与去配算法的设计-最差适应算法

一、设计目的

理解存储管理的功能,掌握动态异长分区内存管理中的最差适应算法。

二、设计要求

本设计要求模拟最差适应算法的分配算法和回收算法。

三、算法设计与分析

1、数据结构分析

为了实现存储资源的分配和回收,操作系统需要记录内存资源使用情况,即哪些区域尚未分配,哪些区域已经分配以及分配给哪些进程等。为此一般需要两个表,一个为分配表, 另外一个为空闲区域表。前者记录已经分配的区域, 后者记录着所有当前未被进程占用的空闲区域,如下图。

空闲区域首地址空闲区域长度
addrsize

显然, 没有记录于表中的区域即为已被进程所占用的非空闲区域,在实际的操作系统中,这些区域登记在进程的PCB中。而PCB中除了关于内存资源的信息外,还有其它大量信息。
由于本设计是对存储管理算法的模拟,所以用一个线程来代表一个进程,用线程驻留区域表来描述线程占用的内存空间,如下图。

线程名称驻留区起始地址驻留区大小
a010
b3020

同时,需要一张表来记录各个线程对内存的请求信息,如下图所示。

线程名称请求大小(kb)预计驻留时间(秒)
thread_1204
thread_2105
thread_356

2、算法分析

分配时取满足申请要求且长度最大的空闲区域。在实现时, 可将系统中所有的空闲区域按照长度由大到小的次序依次记录于空闲区域表中。当进程申请存储空间时, 取第一个表目。如果该表目所对应的区域长度恰好与所申请的区域长度相同, 则将该区域全部分配给申请者。否则将该区域分割为两部分, 一部分的长度与所申请的长度相同, 将其分配给申请者;另一部分即剩余部分的长度为原长度与分配长度之差, 由于剩余部分的长度已经改变,所以应重新将其按长度递减的顺序插入到空闲区域表中。
回收时,不仅要按回收区的首地址查询空闲区表,找到与回收区相临的空闲区,将其合并到相临区中,而且要把合并后的回收区按照长度递减的顺序插入到空闲区域表的适当位置。

3、设计并分析测试数据

假设初始内存布局如下图,图中的起始地址以及大小都以KB来衡量。

起始地址01030508090105125135155
占用者abcde
大小1020203010152010205

由上图可见,初始时共有五个线程驻留在内存,它们是a,b,c,d,e。
线程驻留区表如下。

线程名称驻留区起始地址驻留区大小
a010
b3020
c8010
d10520
e13520

还有五个空闲区,空闲区域表如下图。

空闲区首地址空闲区长度
1020
5030
9015
12510
1555

经过分析我们得到在每种分配算法下这三个线程所申请到的内存情况。下图是最差适应算法分配情况。

线程名称驻留区起始地址驻留区大小
a010
b3020
c8010
d10520
e13520
thread_15020
thread_21010
thread_3905

四、代码

话不多说,直接上代码.
第一个是.h文件,保存的时候记得修改,并且不要和第二段代码放到一起。

#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>

#define MAX_THREAD 3

typedef struct freearea{                    //表示空闲区域的数据结构
	struct freearea *next;                  //指向下一个结点的指针
	int start_address;                     //空闲区起始地址
	int size;                              //空闲区大小
}FREEAREA;

typedef struct require_memory{             //记录线程申请内存的数据结构
    struct require_memory *next;           //指向下一个结点的指针
	char thread_name[10];                //线程名
	int size;                             //申请内存大小(以KB为单位)
	int duration;                         //在内存的驻留时间(以秒为单位)
}REQUIRE_MEMORY;

typedef struct thread_residence_memory{         //描述线程驻留区的数据结构
    struct thread_residence_memory *next;       //指向下一个结点的指针
	char thread_name[10];                     //线程名
	int start_address;                          //驻留区起始地址
	int size;                                   //驻留区大小
}THREAD_RESIDENCE_MEMORY;

FREEAREA init_free_area_table[5]={            
	{NULL,10,20},
	{NULL,50,30},
	{NULL,90,15},
	{NULL,125,10},
	{NULL,155,5}
}; //测试数据:初始空闲区表

REQUIRE_MEMORY init_thread_require_memory_table[3]={ 
	{NULL,"thread_1",20,4},
	{NULL,"thread_2",10,5},
	{NULL,"thread_3",5,6}
}; //测试数据:初始内存申请表

THREAD_RESIDENCE_MEMORY init_thread_residence_memory_table[5]={
	{NULL,"a",0,10},
	{NULL,"b",30,20},
	{NULL,"c",80,10},
	{NULL,"d",105,20},
	{NULL,"e",135,20}
};//测试数据:初始线程驻留区表

FREEAREA *p_free_area_list=NULL;                    //空闲区链首
REQUIRE_MEMORY *p_thread_require_memory_queue=NULL;      //内存申请队列队首
THREAD_RESIDENCE_MEMORY *p_thread_residence_memory_list=NULL; //线程驻留链首
THREAD_RESIDENCE_MEMORY *tail_thread_residence_memory_list=NULL;
 //线程驻留区链尾
CRITICAL_SECTION CS_THREAD_MEMORY_LIST;   //保护线程驻留区链表的临界区
CRITICAL_SECTION CS_SCREEN;                  //保护屏幕的临界区
CRITICAL_SECTION CS_FREEAREA_LIST;          //保护空闲区链表的临界区
HANDLE h_thread[MAX_THREAD];                  //线程句柄数组

void print_space(int num);                                   //输出若干个空格
void display_thread_residence_memory_list();                 //显示线程驻留区表

//最坏适应分配算法的函数
void WF_thread(void *data);                                      //线程函数
void WF_delete_freearea_list();                                 //删除空闲区链表
REQUIRE_MEMORY *WF_initialize_require_memory_list(REQUIRE_MEMORY *init_table,int num); //初始化内存申请链表
void WF_delete_require_memory_list();                           //删除内存申请链表
THREAD_RESIDENCE_MEMORY  *WF_initialize_thread_residence_memory_list
(THREAD_RESIDENCE_MEMORY *init_table,int num);           //初始化线程驻留区链表
void WF_delete_thread_residence_memory_list();                  //删除线程驻留区链表
void WF_insert_freearea(FREEAREA *free_node);              //空闲区结点插入函数
void WF_initialize_freearea_list(FREEAREA *init_table,int num);      //初始化空闲区链表
int WF_require_memory(int size);                                //内存申请函数
void WF_release_memory(int start_address,int size);               //内存释放函数
void WF();                                                 //初始化程序

第二段.cpp文件

#include "variable_partition.h"          //这里注意,第一个文件保存的什么名,引号中间就写什么

void print_space(int num){                           //显示若干个空格
	int i;
	for(i=0;i<num;i++){
		printf(" ");
	}
}

void display_thread_residence_memory_list(){          //显示驻留线程链表
	THREAD_RESIDENCE_MEMORY *p;
	char buffer[20];
   	p=p_thread_residence_memory_list;
	printf("|-------------------|--------------------|------------------|\n");
	printf("| thread_name | start_address(kB) | size(KB) |\n");
	printf("|-------------------|--------------------|------------------|\n");
	while(p!=NULL){
       printf("| %s",p->thread_name);
	   print_space(18-strlen(p->thread_name));
	   printf("| %d",p->start_address);
	   itoa( p->start_address, buffer, 10 );
   	   print_space(19-strlen(buffer));
	   printf("| %d",p->size);
       itoa(p->size, buffer, 10 );
   	   print_space(17-strlen(buffer));
       printf("|\n");
	   p=p->next;
	};
    printf("|-------------------|--------------------|------------------|\n\n");
}


//最差适应分配法:删除空闲区链表
void WF_delete_freearea_list(){
	FREEAREA *temp;
	temp=p_free_area_list;
	while(temp!=NULL){
		temp=p_free_area_list->next;
		free(p_free_area_list);
		p_free_area_list=temp;
	}
	p_free_area_list=NULL;
}


//最差适应分配法:初始化内存申请链表
REQUIRE_MEMORY *WF_initialize_require_memory_list(REQUIRE_MEMORY *init_table,int num){
  REQUIRE_MEMORY *temp;
  REQUIRE_MEMORY *head=NULL;
  REQUIRE_MEMORY *tail=NULL;
  int i;
  for(i=0;i<num;i++){
     temp=(REQUIRE_MEMORY *)malloc(sizeof(REQUIRE_MEMORY));
     strcpy(temp->thread_name,init_table[i].thread_name);
	 temp->size=init_table[i].size;
	 temp->duration=init_table[i].duration;
	 temp->next=NULL;
	 if(head==NULL)
		 head=tail=temp;
	 else{
		 tail->next=temp;
		 tail=tail->next;
	 }
  };
  return head;
}

//最差适应分配法:删除内存申请链表
void WF_delete_require_memory_list(){
	REQUIRE_MEMORY *temp;
	temp=p_thread_require_memory_queue;
	while(temp!=NULL){
		temp=p_thread_require_memory_queue->next;
		free(p_thread_require_memory_queue);
		p_thread_require_memory_queue=temp;
	}
	p_thread_require_memory_queue=NULL;
}

//最差适应分配法:初始化线程驻留区链表
THREAD_RESIDENCE_MEMORY *WF_initialize_thread_residence_memory_list(THREAD_RESIDENCE_MEMORY *init_table,int num){
  THREAD_RESIDENCE_MEMORY *temp;
  THREAD_RESIDENCE_MEMORY *head=NULL;
  THREAD_RESIDENCE_MEMORY *tail=NULL;
  int i;
  for(i=0;i<num;i++){
     temp=(THREAD_RESIDENCE_MEMORY *)malloc(sizeof(THREAD_RESIDENCE_MEMORY));
     strcpy(temp->thread_name,init_table[i].thread_name);
	 temp->start_address=init_table[i].start_address;
	 temp->size=init_table[i].size;
	 temp->next=NULL;
	 if(head==NULL)
		 head=tail=temp;
	 else{
		 tail->next=temp;
		 tail=tail->next;
	 }
  };
  tail_thread_residence_memory_list=tail;
  return head;
}

//最差适应分配法:删除线程驻留区链表
void WF_delete_thread_residence_memory_list(){
	THREAD_RESIDENCE_MEMORY *temp=p_thread_residence_memory_list;
	
	temp=p_thread_residence_memory_list;
	while(temp!=NULL){
		temp=p_thread_residence_memory_list->next;
		free(p_thread_residence_memory_list);
		p_thread_residence_memory_list=temp;
	}
	p_thread_residence_memory_list=NULL;
}


//最差适应分配算法的线程:申请内存,驻留一段时间,释放内存
void WF_thread(void *data){
    int start_address=-1;
	THREAD_RESIDENCE_MEMORY *temp;
	EnterCriticalSection(&CS_SCREEN);
	printf("create thread:%s\n",((REQUIRE_MEMORY *)(data))->thread_name);
	LeaveCriticalSection(&CS_SCREEN);
    
	//申请内存
    while(1){
		start_address=WF_require_memory(((REQUIRE_MEMORY *)(data))->size);
		if(start_address>=0)
			break;
		else
			Sleep(1000);
	}
	temp=(THREAD_RESIDENCE_MEMORY *)malloc(sizeof(THREAD_RESIDENCE_MEMORY));
    strcpy(temp->thread_name,((REQUIRE_MEMORY *)(data))->thread_name);
	temp->start_address=start_address;
	temp->size=((REQUIRE_MEMORY *)(data))->size;
	temp->next=NULL;
	EnterCriticalSection(&CS_THREAD_MEMORY_LIST);
	//加入线程内存驻留区链表
	tail_thread_residence_memory_list->next=temp;
	tail_thread_residence_memory_list=tail_thread_residence_memory_list->next;
    LeaveCriticalSection(&CS_THREAD_MEMORY_LIST);
	//显示线程内存驻留区链表
	EnterCriticalSection(&CS_SCREEN);
	printf("after %s %s\n",((REQUIRE_MEMORY *)(data))->thread_name,"get memory:");
	display_thread_residence_memory_list();
	LeaveCriticalSection(&CS_SCREEN);
	
	Sleep(((REQUIRE_MEMORY *)(data))->duration);
	//释放内存
	WF_release_memory(start_address,((REQUIRE_MEMORY *)(data))->size);
}

//最差分配算法的空闲区结点插入函数
void WF_insert_freearea(FREEAREA *free_node){
    FREEAREA *p;
    FREEAREA *p_next;
	 
	 if(p_free_area_list==NULL)
		 p_free_area_list=free_node;
	 else{
       p=p_next=p_free_area_list;
	   while(p_next!=NULL&&free_node->size<p_next->size){
		 p=p_next;
		 p_next=p_next->next;
	   }
	   if(p_next==NULL)      //应插入到尾部
		 p->next=free_node;
	   else
		 if(p==p_next){  //应插入到头部
		    free_node->next=p;
		    p_free_area_list=free_node;
		 }
		 else{           //应插入到p与p_next之间
			 free_node->next=p_next;
			 p->next=free_node;
		 }
	 }
}

//最差适应分配法:初始化空闲区链表
void WF_initialize_freearea_list(FREEAREA *init_table,int num){
  FREEAREA *temp;
  int i;
  for(i=0;i<num;i++){
     temp=(FREEAREA *)malloc(sizeof(FREEAREA));
     temp->start_address=init_table[i].start_address;
	 temp->size=init_table[i].size;
	 temp->next=NULL;
	 WF_insert_freearea(temp);
  }
}
//最差适应分配算法的内存申请函数
int WF_require_memory(int size){
	//请读者自己实现这段代码
	int start_address;//定义需要找到的空闲区起始地址
    FREEAREA* p;//定义移动指针 
    FREEAREA* p_next;//指向移动指针的下一个地址 
    FREEAREA* ptr;//记录找到的最大的空闲区 
    FREEAREA* ptr_f;//记录找到的最大的空闲区的上一个区域 
    FREEAREA* p_free_area_list_next;//定义头指针的下一个地址 
    EnterCriticalSection(&CS_FREEAREA_LIST);  //保护空闲表临界区
    p=p_free_area_list;//空闲区头指针,下一个指针均指向空闲区链表 
    p_next=p->next;ptr=p;ptr_f=p;
    p_free_area_list_next=p_free_area_list->next;
    start_address=-1;
    while (p->next!=NULL) {//找到空闲分区中尺寸最大的结点
        if(ptr->size<p_next->size){
        	ptr=p_next;
        	ptr_f=p;
        }
        p=p_next;
        p_next=p_next->next;
    }
    if(size==ptr->size){//看找到的空闲区是否等于进程的请求
    	if(ptr==p_free_area_list){
    		start_address=p_free_area_list->start_address;
    		p_free_area_list=p_free_area_list_next; 
    		free(ptr);
    	}
    	else{
    		start_address=ptr->start_address;
    		ptr_f->next=ptr->next;
    		
    		free(ptr);
    	}
    }
    if(size<ptr->size){//如果空闲区大于进程的请求
    	start_address=ptr->start_address;
    	ptr->start_address+=size;
    	ptr->size-=size;
    }
    //如果小于,分配不了 
    LeaveCriticalSection(&CS_FREEAREA_LIST);    //释放空闲表临界区
    return start_address;
}
//最差适应分配算法:内存释放函数
void WF_release_memory(int start_address,int size){
  //请读者自己实现这段代码
	FREEAREA *p,*pp,*p_pre,*p_next,*temp=p_free_area_list;
    int flag=0;//记录合并方式的标识 
    for(p=p_free_area_list;p!=NULL;p=p->next){//通过循环来查找哪里能合并 
    	if(p->start_address==start_address+size){//第一种合并方法 
            ++flag;
            p_next=p;
        }
		else if(p->start_address+p->size==start_address){//第二种合并方法 
            flag+=2;
            p_pre=p;
        }
    }
    if(flag==0){//如果没有合并区域 
        p=(FREEAREA *)malloc(sizeof(FREEAREA));
        p->start_address=start_address;
        p->size=size;
        WF_insert_freearea(p);
    }
	else if(flag==1||flag==2){
        if(flag==1){//如果合并方式为第一种 
            p_next->start_address-=size;
            p_next->size+=size;
            p=p_next;
        }
		else{//如果合并方式为第二种 
            p_pre->size+=size;
            p=p_pre;
        }
        if(p==p_free_area_list){}
        else{//如果指针p不为头节点 
            while(temp->next!=p){
            	temp=temp->next;
            }
            if(p->size>=p_free_area_list->size){
                temp->next=p->next;
                p->next=p_free_area_list;
                p_free_area_list=p;
            }
			else{
                if(p->size<=temp->size){}
                else{
                    p_pre=p_free_area_list;
                    while(p_pre->next->size>p->size){
                    	p_pre=p_pre->next;
                    }
                    temp->next=p->next;
                    p->next=p_pre->next;
                    p_pre->next=p;
                }
            }
        }
    }
	else{
        if(p_pre==p_free_area_list){
            p_pre->size+=p_next->size+size;
            while(temp->next!=NULL){
            	if(temp->next==p_next){
            		temp->next=p_next->next;
            	}
            }
            free(p_next);
        }
		else if(p_next==p_free_area_list){
            p_next->start_address=p_pre->start_address;
            p_next->size+=p_pre->size+size;
            while(temp->next!=NULL){
            	if(temp->next==p_pre){
                	temp->next=p_pre->next;
                }
            }
            free(p_pre);
        }
		else{
            while(temp->next!=NULL){
                if(temp->next==p_pre){
                	temp->next=p_pre->next;
                }
                if(temp->next==p_next){
                	temp->next=p_next->next;
                }
            }
            p=(FREEAREA *)malloc(sizeof(FREEAREA));
            p->start_address=p_pre->start_address;
            p->size=p_pre->size+p_next->size+size;
            pp=p_free_area_list;
            while(pp->next!=NULL){
                if (pp->next==p_pre){
                	pp->next=p_pre->next;
                }
                else if(pp->next==p_next){
                	pp->next=p_next->next;
                }
                if(pp->next!=NULL){
                	pp=pp->next;
                }
            }
            free(p_pre);
            free(p_next);
            WF_insert_freearea(p);
        }
    }
    EnterCriticalSection(&CS_THREAD_MEMORY_LIST);//访问线程驻留区域 
    THREAD_RESIDENCE_MEMORY *rp=p_thread_residence_memory_list,*f;
    while(rp->next->start_address!=start_address)
        rp=rp->next;
    f=rp->next;
    rp->next=f->next;
    free(f);
    while (rp->next!=NULL)
        rp=rp->next;
    tail_thread_residence_memory_list=rp;
    LeaveCriticalSection(&CS_THREAD_MEMORY_LIST);
}

//最差适应分配算法
void WF( ){
  int i=0;
    REQUIRE_MEMORY *p;
   	HANDLE h_thread[MAX_THREAD];
	InitializeCriticalSection(&CS_THREAD_MEMORY_LIST);
    InitializeCriticalSection(&CS_FREEAREA_LIST);
	InitializeCriticalSection(&CS_SCREEN);
	printf("最坏适应分配算法\n");
    WF_initialize_freearea_list(init_free_area_table,5);
p_thread_require_memory_queue=WF_initialize_require_memory_list(init_thread_require_memory_table,3);
p_thread_residence_memory_list=WF_initialize_thread_residence_memory_list(init_thread_residence_memory_table,5);
    p=p_thread_require_memory_queue;
    while(p!=NULL){
      h_thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WF_thread),p,0,NULL);
      i++;
	  p=p->next;
    };
    //等待所有线程结束
    WaitForMultipleObjects(MAX_THREAD,h_thread,TRUE,-1);

	//显示驻留线程链表
	EnterCriticalSection(&CS_SCREEN);
	printf("after all threads have finished:\n");
	display_thread_residence_memory_list();
	LeaveCriticalSection(&CS_SCREEN);

	//删除各种链表
	WF_delete_freearea_list();
	WF_delete_require_memory_list();
	WF_delete_thread_residence_memory_list();

	getch();
    printf("\n");	
}

int main(){
WF( );
}

最后,数据都是可以自己定义修改的。其实我写的内存分配函数并没有按照要求的那样,找到之后重新排序,只是在每次都去找最大的。对于内存释放函数并不是本人写的,但是释放函数是有一个重排序的过程,想要借用的小伙伴可以注意一下。

  • 6
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是C语言实现最差适应算法的代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 // 内存块最大数量 typedef struct node { int size; // 内存块大小 int start; // 内存块起始位置 int status; // 内存块状态,0表示空闲,1表示占用 } Node; Node memory[MAX_SIZE]; // 内存块数组 int memory_size = 0; // 内存块数量 // 初始化内存块 void initMemory() { memory[0].size = 1000; // 初始化一个大小为1000的内存块 memory[0].start = 0; memory[0].status = 0; memory_size = 1; } // 显示内存块状态 void showMemory() { printf("Memory Status:\n"); for (int i = 0; i < memory_size; i++) { printf("Block %d: start=%d, size=%d, status=%d\n", i, memory[i].start, memory[i].size, memory[i].status); } printf("\n"); } // 最差适应算法内存 int allocateMemory(int size) { int max_block = -1; // 记录最大内存块号 int max_size = 0; // 记录最大空闲内存块大小 for (int i = 0; i < memory_size; i++) { // 找到空闲内存块中大小最大的 if (memory[i].status == 0 && memory[i].size >= size && memory[i].size > max_size) { max_block = i; max_size = memory[i].size; } } if (max_block == -1) { // 没有合适的内存块 printf("No available memory block.\n"); return -1; } // 分内存 int start = memory[max_block].start; memory[max_block].status = 1; if (memory[max_block].size == size) { // 如果空闲内存块大小刚好等于需要分的大小,直接返回其起始位置 return start; } else { // 如果空闲内存块大小大于需要分的大小,将其分割成两个内存块 int new_block = memory_size; memory_size++; memory[new_block].size = memory[max_block].size - size; memory[new_block].start = start + size; memory[new_block].status = 0; memory[max_block].size = size; return start; } } // 释放内存 void freeMemory(int start) { for (int i = 0; i < memory_size; i++) { if (memory[i].start == start) { // 找到对应内存块 memory[i].status = 0; // 合并相邻的空闲内存块 if (i > 0 && memory[i - 1].status == 0) { memory[i - 1].size += memory[i].size; for (int j = i; j < memory_size - 1; j++) { memory[j] = memory[j + 1]; } memory_size--; i--; } if (i < memory_size - 1 && memory[i + 1].status == 0) { memory[i].size += memory[i + 1].size; for (int j = i + 1; j < memory_size - 1; j++) { memory[j] = memory[j + 1]; } memory_size--; } break; } } } int main() { initMemory(); // 初始化内存块 showMemory(); // 显示内存块状态 int start1 = allocateMemory(200); // 分200字节内存 printf("Allocate 200 bytes memory at %d.\n", start1); showMemory(); int start2 = allocateMemory(300); // 分300字节内存 printf("Allocate 300 bytes memory at %d.\n", start2); showMemory(); int start3 = allocateMemory(400); // 分400字节内存 printf("Allocate 400 bytes memory at %d.\n", start3); showMemory(); freeMemory(start2); // 释放300字节内存 printf("Free 300 bytes memory at %d.\n", start2); showMemory(); int start4 = allocateMemory(500); // 分500字节内存 printf("Allocate 500 bytes memory at %d.\n", start4); showMemory(); return 0; } ``` 这个程序中,最差适应算法的实现在 `allocateMemory()` 函数中。它首先遍历所有空闲内存块,找到大小最大的那个,然后将其分出去。如果需要分的大小小于找到的空闲内存块大小,还需要将其分割成两个内存块,一个占用,一个保留。在 `freeMemory()` 函数中,释放内存时还需要合并相邻的空闲内存块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值