模拟了操作系统作业中内存动态分配问题。是一个简单的实现。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <tgmath.h>
#include <string.h>
#define n 10 //假定系统允许的最大作业数量为n
#define m 10 //假定系统允许的空闲区表最大为m
#define minsize 1000
typedef struct workPcb{
char name[4];//name是字符串的首地址,char * a a保存着储存字符串的地址
double length;
} workPcb;
struct{
char name[4];
double address; //已分分区起始地址
double length; //已分分区长度,单位为字节
int flag; //已分配区表登记栏标志,“0”表示空栏目,实验中只支持一个字符的作业名
}used_table[n]; //已分配区表
//空闲区表的定义:
struct
{ double address; //空闲区起始地址
double length; //空闲区长度,单位为字节
int flag; //空闲区表登记栏标志,用“0”表示空栏目,用“1”表示未分配
}free_table[m]; //空闲区表
//找到最小的
double freeArea=100*2*2*2*2*2*2*2*2*2*2;
void distribution(workPcb* workPcb){
int k=-1,i=0;
while(i<=m){
if(free_table[i].flag==1){//当第i个分区没有被分配时
if(free_table[i].length>=workPcb->length){//满足长度的分区
if(k=-1)//找出满足条件的最小的分区
k=i;
else{
if(free_table[i].length<free_table[k].length){
k=i;
}
}
}
}
i++;
}
//已经遍历完所有的分区
if(k!=-1){
double ad,xk;
if(free_table[k].length-workPcb->length<=minsize){//当满足最小值的时候全部分配
free_table[k].flag=0;
ad=free_table[k].address;//分配的起始地址
xk=free_table[k].length;//分配的长度
free_table[k].length=0;
}else{
ad=free_table[k].address;
free_table[k].address+=workPcb->length;
xk=workPcb->length;
free_table[k].length=free_table[k].length-workPcb->length;
}
//寻找空闲的已分配表
int j=0;
while(j<=9){
if(used_table[j].flag==0){//如果有空闲的已分配表那么就分配
strcpy(used_table[j].name, workPcb->name);
used_table[j].address=ad;
used_table[j].length=xk;
used_table[j].flag=1;
break;
}
else
j++;
}//如果j<10就分配成功
if(j!=10){
printf("分配成功\n");
}else{//如果分配不成功,那么还回空闲分配区的长度
if(free_table[k].length==0){
free_table[k].length=xk;
}else{
free_table[k].length=free_table[k].length+workPcb->length;
used_table[j].flag=0;
free_table[k].address-=workPcb->length;
}
printf("分配空间不足");
}
}else{
printf("空闲空间不足,失败\n");
}
}
void reclaim(workPcb *J){
int s=0,a=0;
double S,L;
while(s<=9){
a=strcmp(J->name,used_table[s].name);
if(a==0){//找到作业与未找到作业
S=used_table[s].address;
L=used_table[s].length;
used_table[s].flag=0;
int j=-1;//相邻下空闲区栏
int k=-1;
double upS,doS;//相邻上空闲区栏
upS=used_table[s].address+used_table[s].length;//应该的上分区和下分区//应该的上分区和下分区
int q=0;
while(q<=9){//判断有没有上下分区
if(free_table[q].address==upS){
k=q;
}
if(free_table[q].address+free_table[q].length==S){
j=q;
}
q++;
}
if(k!=-1){//存在上分区
if(j!=-1){//两个分区都存在
free_table[k].length=L+free_table[k].length+free_table[j].length;
free_table[k].address-=L+free_table[j].length;
free_table[j].flag=0;
printf("回收成功");
}
else{//只存在上分区
free_table[k].length=L+free_table[k].length;
free_table[k].address-=L;
printf("回收成功");
}
}else{
if(j!=-1){//只存在下分区
free_table[j].length=L+free_table[j].length;
printf("回收成功");
}else{//哪个分区都不存在
int t=0;
while(t<=9){//寻找一块分配表里的新地方
if(free_table[t].flag==0){
break;
}
t++;
}
if(t==10){
used_table[s].flag=1;
printf("作业回收失败,空闲分区表不足");
}else{//设置属性
free_table[t].address=S;
free_table[t].length=L;
free_table[t].flag=1;
printf("回收成功");
}
}
}
break;//找到了就break了
}else
s++;
}
if(s==10){
printf("未找到作业");
}
}
int main(){
int jud=1;
int choice=3;
printf("欢迎进入作业分配与回收的程序,1为分配,2为回收,3退出程序,4查看空闲表和已分配表\n");
scanf("%d",&choice);
workPcb workPcb;//一个作业
free_table[0].address=10*2*2*2*2*2*2*2*2*2*2;//除去了操作系统后的低地址
free_table[0].length=freeArea;//初始化空闲表
free_table[0].flag=1;//空闲区1代表可分配
for(int i=0;i<=9;i++){
used_table[i].flag=0;
}
//初始化已分配表 已分配表0代表空
while(jud){
switch(choice){
case 1:{
printf("请输入作业名,作业长度\n");
scanf("%s%lf",&workPcb.name,&workPcb.length);//填写作业名与长度
printf("作业名:%s作业大小:%lf\n",workPcb.name,workPcb.length);
distribution(&workPcb);
break;
}
case 2:{
printf("请输入作业名\n");
scanf("%s",&workPcb.name);//填写作业名与长度
reclaim(&workPcb);
break;
}
case 3:{
jud=0;
printf("拜拜");
break;
}
case 4:{
printf("------------空闲表状态\n");
for(int i=0;i<=9;i++){
if(free_table[i].flag==0){
free_table[i].address=0;
free_table[i].length=0;
}
printf("空闲区域开始地址:%lf大小:%lf状态:%d\n",free_table[i].address,free_table[i].length,free_table[i].flag);
}
printf("------------已分配表状态\n");
for(int i=0;i<=9;i++){
if(used_table[i].flag==0){
used_table[i].name[0]=0;
used_table[i].address=0;
used_table[i].length=0;
}
printf("已分配区域作业名:%s开始地址:%lf大小:%lf状态:%d\n",used_table[i].name,used_table[i].address,used_table[i].length,used_table[i].flag);
}
break;
}
default:{
printf("输入有错误,请重试\n");
}
}
if(jud!=0){
printf("欢迎进入作业分配与回收的程序,1为分配,2为回收,3退出程序,4查看作业状态\n");
scanf("%d",&choice);
}
}
return 0; //进行分配任务
}