姓名:李瑶
学号: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的空间。
浙公网安备 33010602011771号