姓名:李瑶

学号:201821121002

班级:计算1811

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

需要定义一个结构体allocated_block,表示每个进程分配到的内存块描述:

包括进程标识符、进程大小等,当释放进程内存时,就将成功释放的进程块节点从链表中删除。

/*每个进程分配到的内存块描述*/
typedef struct allocated_block{
	int pid;
	int size;
	int start_addr;
	char process_name[PROCESS_NAME_LEN];
	struct allocated_block *next;
}AB;

 

 2. 记录空闲分区

需要定义一个结构体free_block_type描述每一个空闲块的数据结构:

包括空闲块大小、空闲块起始地址等。

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

/*描述每一个空闲块的数据结构*/
typedef struct free_block_type{
	int size;
	int start_addr;
	struct free_block_type *next;
}FBT;

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 shengyu = tmp->size - request;
			if(shengyu <= min_mem_size){
				//剩余过小全部分配
				ab->size = tmp->size;
				if(tmp == free_block){
					free_block = free_block->next;
					free(tmp);
				}else{
					FBT *t = free_block;
					while(t->next != tmp){
						t = t->next;
					}
					t->next = tmp->next;
					free(tmp);
				}
			}else{
				//切割出分配走的内存
				tmp->size = shengyu;
				tmp->start_addr = tmp->start_addr + request;
			}
			return ;
		}
		tmp = tmp->next;
	}
}

void rearrange_FF(){
	/*首次适应算法,空闲区大小按起始地址升序排序*/
	//这里使用冒泡排序方法
	if(free_block == NULL || free_block->next == NULL)
		return;
	FBT *t1,*t2,*head;
	head = free_block;
	for(t1 = head->next;t1;t1 = t1->next){
		for(t2 = head;t2 != t1;t2=t2->next){
			if(t2->start_addr > t2->next->start_addr){
				int tmp = t2->start_addr;
				t2->start_addr = t2->next->start_addr;
				t2->next->start_addr = tmp;

				tmp = t2->size;
				t2->size = t2->next->size;
				t2->next->size = tmp;
			}
		}
	}
}

4. 内存释放算法

//释放链表节点
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){
	/* 将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_FF();

	//合并可能分区;即若两空闲分区相连则合并
	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(){
	AB *ab;
	int pid;
	printf("Kill Process,pid=");
	scanf("%d",&pid);
	ab = find_process(pid);
	if(ab!=NULL){
		free_mem(ab);	//释放ab所表示的分配表
		dispose(ab);	//释放ab数据结构节点
		return 0;
	}else{
		return -1;
	}
}

5. 运行结果

产生测试结果:

int main(int argc, char const *argv[]){
    /* code */
    int sel1,sel2; 
    int total=0; //记录分配内存的次数 
    free_block = init_free_block(mem_size); //初始化空闲区
    
    Prc prc[PROCESS_NUM];//存放要加载的进程
    init_program(prc,PROCESS_NUM);//对这几个程进程进行初始化 
    srand( (unsigned)time( NULL ) );  
    
    for(int i=0;i<DATA_NUM;++i)
    {
        /*
           sel1=0表示为某进程分配内存空间 
           sel1=1表示为释放某进程占用的内存空间 
        */ 
        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();//显示 
        }
    }
}

 

 

 

解释程序运行结果

最初设置空闲分区的内存范围为0~1024

首先创建了大小为207的进程,剩余空间为817;

又创建了大小为239的进程单元,起始地址从207开始,剩余空间变为446;

接着释放了进程为3,4,5,6的进程单元数,于是空闲分区剩有了释放进程内存单元数的空间和起始地址为446,大小为89的空间。

 

posted on 2020-05-17 11:20  霓袅  阅读(368)  评论(0编辑  收藏  举报