操作系统——动态分区分配模拟程序

编写一个动态分区分配算法模拟程序,加深对动态分区存储管理方式及其实现过程的理解。

要求:

空闲分区通过空闲区链进行管理,在内存分配时,优先考虑低地址部分的空闲区。 
分别采用首次适应算法、最佳适应算法和最坏适应算法模拟内存空间的动态分配与回收,每次分配和回收后显示出空闲区链的详细情况(说明:在申请不成功时,需要打印当前内存的占用情况信息)。 
进程对内存空间的申请和释放可由用户自定义输入。 
参考请求序列如下: 
(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<stdio.h>
#include<stdlib.h>
#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 <p->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 <p->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 <p->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

            }
        }
    }
}


猜你喜欢

转载自blog.csdn.net/baidu_36004106/article/details/80521792