编写一个动态分区分配算法模拟程序,加深对动态分区存储管理方式及其实现过程的理解。
要求:
空闲分区通过空闲区链进行管理,在内存分配时,优先考虑低地址部分的空闲区。
分别采用首次适应算法、最佳适应算法和最坏适应算法模拟内存空间的动态分配与回收,每次分配和回收后显示出空闲区链的详细情况(说明:在申请不成功时,需要打印当前内存的占用情况信息)。
进程对内存空间的申请和释放可由用户自定义输入。
参考请求序列如下:
(1) 初始状态下可用内存空间为640KB;
(2) 进程1申请130KB;
(3) 进程2申请60KB;
(4) 进程3申请100KB;
(5) 进程2释放60KB;
(6) 进程4申请200KB;
(7) 进程3释放100KB;
(8) 进程1释放130KB;
(9) 进程5申请140KB;
(10) 进程6申请60KB;
(11) 进程7申请50KB;
(12) 进程6释放60KB。
测试用例格式如下:
输入:
动态分区分配算法选择
可用内存空间容量
序号/进程号/申请或释放操作/申请或释放的容量
其中:
(1) 动态分区分配算法:1—-首次适应,2—-最佳适应,3—-最坏适应
(2) 申请或释放操作: 1—-申请操作,2—-释放操作
输出:
序号/内存空间状态1/内存空间状态2……
内存空间状态表示分为两种情况:
(1) 内存空间被占用:
内存空间起始地址-内存空间结束地址.1.占用的进程号
(2) 内存空间空闲
内存空间起始地址-内存空间结束地址.0
/*
**@Unintented
**@2017.12.14
*/
#include
#include
#pragma warning(disable:4996)//防止scanf报错(VS2013)
struct proc{
int squ;//进程序号
int pid;//进程号
int act;//进程操作
int size;//申请或释放的容量
}pro;//存放各进程的请求
struct me{
int me_size;//若空闲:分区的可用大小,若被占用:被占用的大小
int head;//起始位置
int tail;//结束位置
int pid;//占用的进程号,未被占用时(-1)
struct me *next;//物理下一块链
};//存放各分区
typedef me Me;
Me *top;//头结点
void Initial(int Me_size){
top = (Me*)malloc(sizeof(Me));
top->me_size = Me_size;
top->pid = -1;
top->head = 0;
top->tail = Me_size - 1;
top->next = NULL;
}
int pro_num;//存放操作数目
int squ=1;//输出的序号
void FF();//最先适应
void BF();//最好适应
void WF();//最差适应
void print();
int main(){
int op;//算法类型
int Me_size;//内存总量
scanf("%d", &op);
scanf("%d", &Me_size);
Initial(Me_size);
while (scanf("%d/%d/%d/%d", &pro.squ, &pro.pid, &pro.act, &pro.size) == 4){
switch (op){
case 1:
FF();
break;
case 2:
BF();
break;
case 3:
WF();
break;
}
print();
}
}
void print(){
Me *p;
p = top;
printf("%d", squ++);
while (p != NULL){
if (p->pid != -1)
printf("/%d-%d.1.%d", p->head, p->tail, p->pid);//内存被占用时
else
printf("/%d-%d.0", p->head, p->tail);//内存空闲时
p = p->next;
}
printf("\n");
}
void FF(){
Me *p;
Me *temp;
temp = top;//用来跟踪释放内存的节点的前一节点
p = top;
if (pro.act == 1){//申请内存
while (p !=NULL){
if (p->pid != -1){//该块已被占用
p = p->next;
continue;
}
else{
if (pro.size > p->me_size){//该块内存过小
p = p->next;
continue;
}
else if(pro.size me_size ){//申请内存成功且连续内存块有剩余
Me *q;
q = (Me*)malloc(sizeof(Me));
q->next = p->next;
p->next = q;//插入节点q,代表将原内存分割成连续两部分
q->head = p->head + pro.size ;
q->pid = -1;
q->me_size = p->me_size - pro.size;
q->tail = p->tail;//更新切割出的块
p->me_size = pro.size;
p->pid = pro.pid;
p->tail = p->head + pro.size - 1;//更新申请成功的块
break;
}
else{//申请成功且大小恰好等于连续内存块大小
p->pid = pro.pid;
break;
}
}
}
}
else if (pro.act == 2){//请求释放内存
while (p != NULL){
if (p->pid != pro.pid){//进程号不匹配
temp = p;
p = p->next;
continue;
}
else if (p->pid == pro.pid){//进程号匹配
if (p->next->pid == -1){//释放的内存后一块为空,则合并
p->me_size = pro.size + p->next->me_size;//此题中占用多大,则释放多大
p->pid = -1;
p->tail = p->next->tail;
p->next = p->next->next;
}
else{//释放内存的后一块不为空
p->pid = -1;
}
if (temp->pid == -1){//释放内存的前一块也为空
temp->me_size = temp->me_size + p->me_size;
temp->tail = p->tail;
temp->next = p->next;
}
break;//一定要前后都判断是否为空后才break
}
}
}
}
void BF(){
Me *p;
Me *m;//分配内存时,用于查找对应块
Me *temp;//用来跟踪释放内存的节点的前一节点
int t = -1;//存储最佳块的头位置,为-1表示未找到可用的内存块
int flag = 0;//标志最佳块的大小是否等于进程申请的大小
int best_size = 100000;//用来寻找最佳块
temp = top;
p = top;
m = top;
if (pro.act == 1){//申请内存
while (p != NULL){//此循环用于寻找最适合该进程的块
if (p->pid != -1){//该块已被占用
p = p->next;
continue;
}
else{
if (pro.size > p->me_size){//该块内存过小
p = p->next;
continue;
}
else if (pro.size me_size){//不断更新更好的块
if (p->me_size < best_size){
best_size = p->me_size;
t = p->head;
}
p = p->next;
continue;
}
else{//若内存块大小与进程申请的块的大小相等,则必为最佳块
t = p->head;
flag = 1;
break;
}
}
}
if (t == -1){//内存未给该进程分配空间,无合适块
return;
}
else if(t!=-1&&flag==1){//最佳块的大小等于进程申请的大小
while (m != NULL){
if (m->head == t){
p->pid = pro.pid;
return;
}
m = m->next;
}
}
else if (t != -1 && flag != 1){//最佳块的大小不等于进程申请的大小
while (m != NULL){
if (m->head == t){
Me *q;
q = (Me*)malloc(sizeof(Me));
q->next = m->next;
m->next = q;//插入节点q,代表将原内存分割成连续两部分
q->head = m->head + pro.size;
q->pid = -1;
q->me_size = m->me_size - pro.size;
q->tail = m->tail;//更新切割出的块
m->me_size = pro.size;
m->pid = pro.pid;
m->tail = m->head + pro.size - 1;//更新申请成功的块
return;
}
m = m->next;
}
}
}
else if (pro.act == 2){//请求释放内存
while (p != NULL){
if (p->pid != pro.pid){//进程号不匹配
temp = p;
p = p->next;
continue;
}
else if (p->pid == pro.pid){//进程号匹配
if (p->next->pid == -1){//释放的内存后一块为空,则合并
p->me_size = pro.size + p->next->me_size;//此题中占用多大,则释放多大
p->pid = -1;
p->tail = p->next->tail;
p->next = p->next->next;
}
else{//释放内存的后一块不为空
p->pid = -1;
//p->state = 0;
}
if (temp->pid == -1){//释放内存的前一块也为空
temp->me_size = temp->me_size + p->me_size;
temp->tail = p->tail;
temp->next = p->next;
}
break;//一定要前后都判断是否为空后才break
}
}
}
}
void WF(){
Me *p;
Me *m;//分配内存时,用于查找对应块
Me *temp;//用来跟踪释放内存的节点的前一节点
int t = -1;//存储最佳块的头位置,为-1表示未找到可用的内存块
int flag = 0;//标志最佳块的大小是否等于进程申请的大小
int worst_size = 0;//用来寻找最佳块
temp = top;//此处在释放第一块内存后判断前一块是否为空时有坑
p = top;
m = top;
if (pro.act == 1){//申请内存
while (p != NULL){//此循环用于寻找最适合该进程的块
if (p->pid != -1){//该块已被占用
p = p->next;
continue;
}
else{
if (pro.size > p->me_size){//该块内存过小
p = p->next;
continue;
}
else if (pro.size me_size){//不断更新更好的块
if (p->me_size > worst_size){
worst_size = p->me_size;
t = p->head;
}
p = p->next;
continue;
}
else{//若内存块大小与进程申请的块的大小相等,则必为最佳块
t = p->head;
flag = 1;
break;
}
}
}
if (t == -1){//内存未给该进程分配空间,无合适块
return;
}
else if (t != -1 && flag == 1){//最佳块的大小等于进程申请的大小
while (m != NULL){
if (m->head == t){
p->pid = pro.pid;
return;
}
m = m->next;
}
}
else if (t != -1 && flag != 1){//最佳块的大小不等于进程申请的大小
while (m != NULL){
if (m->head == t){
Me *q;
q = (Me*)malloc(sizeof(Me));
q->next = m->next;
m->next = q;//插入节点q,代表将原内存分割成连续两部分
q->head = m->head + pro.size;
q->pid = -1;
q->me_size = m->me_size - pro.size;
q->tail = m->tail;//更新切割出的块
m->me_size = pro.size;
m->pid = pro.pid;
m->tail = m->head + pro.size - 1;//更新申请成功的块
return;
}
m = m->next;
}
}
}
else if (pro.act == 2){//请求释放内存
while (p != NULL){
if (p->pid != pro.pid){//进程号不匹配
temp = p;
p = p->next;
continue;
}
else if (p->pid == pro.pid){//进程号匹配
if (p->next->pid == -1){//释放的内存后一块为空,则合并
p->me_size = pro.size + p->next->me_size;//此题中占用多大,则释放多大
p->pid = -1;
p->tail = p->next->tail;
p->next = p->next->next;
}
else{//释放内存的后一块不为空
p->pid = -1;
//p->state = 0;
}
if (temp->pid == -1&&p->head ==0){//释放内存的前一块也为空,p->head==0条件是为了防止释放链表第一块时重复加内存
temp->me_size = p->me_size;
temp->tail = p->tail;
temp->next = p->next;
}
else if(temp->pid==-1&&p->head!=0){//!!!注意若条件语句中有两个相等或不相等的判断条件,则要考虑四种情况
temp->me_size =temp->me_size + p->me_size;
temp->tail = p->tail;
temp->next = p->next;
}
break;//一定要前后都判断是否为空后才break
}
}
}
}