操作系统 进程控制 实验(C语言)

进程控制

基本要求

  模拟操作系统内核对进程的控制和管理:包括进程的创建和撤销、进程状态的切换和简单的内存空间管理。

实验提示

  1、 定义管理每个进程的数据结构PCB:包含进程名称、队列指针、分配的物理内存区域(基址和长度)。每创建一个进程时,需要为其创建PCB并分配空闲内存空间,对PCB进行初始化,并加入就绪队列。(斜体为可选)

可参考如下数据结构(动态形式):

struct PCB{

char name[8];

struct PCB *next;

...

};

struct PCB *ready,*blocked,*running;

创建进程时申请空白PCB:

struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB));

并把新建进程的PCB添加到就绪队列末尾:

add(ready,p);

其中,ready为就绪队列头节点,并在开始处分配了空间;add函数是链表中添加节点函数,代码参考如下:

 

void add(struct PCB *head, struct PCB *process){

   struct PCB *tmp=head;

   while(tmp->next!=NULL)

       tmp=tmp->next;

   tmp->next=process;

   process->next=NULL;

}

 

2、 模拟触发进程状态转换的事件:采用键盘控制方法来模拟触发进程状态切换的事件(例如输入1代表创建新进程、2执行进程时间片到、3阻塞执行进程、4唤醒第一个阻塞进程、5终止执行进程),实现对应的控制程序。

3、 根据当前发生的事件对进程的状态进行切换,并显示出当前系统中的执行队列、就绪队列和阻塞队列。

4、 *(选做)完成可变分区的分配与回收,创建进程的同时申请一块连续的内存空间,在PCB中设置好基址和长度,结束进程时回收分配的内存空间。分配可采用首次适应、最佳适应或最差适应算法,碎片大小为2Kb,最后回收所有进程的空间,对空间分区的合并。可以查看进程所占的空间和系统空闲空间。

可以用一个链表(如图1-1所示)来维护已分配的和空闲的内存段,其中一个段或者包含一个进程,或者是两个进程之间的空闲段。 在图1-1中,链表的每一项包含四个值域。第一个值域表示内存段是空闲或占用(例如,空闲段用H表示,进程占用的段用P表示);第二个值域表示内存段的起始位置,第三个值域表示内存段的长度;第四个值域为指向链表下一项的指针。该链表按照内存段的起始地址进行从小到大排序。这样排序的好处是方便内存空间的回收。一个要终止的进程一般会有两个邻居(除了在内存顶端和内存底端的进程)。邻居可能是进程也可能是空闲段。根据两个邻居的不同类型,可以分为四种回收情况(如图1-2所示)。在图1-2(a)中,对链表的更新只需要将P置为H;在图1-2(b)和(c)中,需要将P置为H,并将该项与另外一个相邻的空闲段的项合并为一项;在图1-2(d)中,需要将该项和两个邻居合并为一项。考虑到合并空闲段需要查看邻居,因此用双向链表会比单向链表更加方便。

 

 

 

1-1. (a) 内存空间的示例,有5个进程和3个空闲段,阴影部分表示空闲段。

(b) 管理内存空间的链表

 

 

 

1-2. 对终止的进程X的四种内存回收情况(阴影代表空闲区)

实验代码

 

#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;

struct PCB{
    char name[8];
    struct PCB *next;
};

struct PCB *ready,*blocked,*running;
struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB));

//插入队列 
void add(struct PCB *head,struct PCB *process){
    struct PCB *tmp=head;
    while(tmp->next!=NULL)
        tmp=tmp->next;
    tmp->next=process;
    process->next=NULL;
}

//出队列 
struct PCB *movefirst(struct PCB *head){ 
    struct PCB *tmp=head->next;
    if(tmp!=NULL)
    {
        head->next=tmp->next;
        tmp->next=NULL;
    }
    return tmp;
};

//创建进程 
void creat()
{
    struct PCB *tmp;
    char name[10];
    cout<<"输入进程名字:";
    cin>>name;
    tmp=(struct PCB*)malloc(sizeof(struct PCB));
    strcpy(tmp->name,name);  //字符串复制函数 
    tmp->next=NULL;
    add(ready,tmp);
    if(running==NULL)   //如果当前没有正在执行的进程就将新创建的进程运行 
        running=movefirst(ready);
}

//时间片到 
void timeout(){
    if(ready->next==NULL)          //  容错处理
        cout<<"\t\t就绪队列为空!"<<endl;
    if(running!=NULL)
    {
        add(ready,running);
        running=movefirst(ready);
    }
    else
        running=movefirst(ready);
}

//阻塞进程 
void block(){
    if(running!=NULL)
    {
        add(blocked,running);
        running=movefirst(ready);
    }
    else
        cout<<"\t\t没有运行的进程,无法阻塞!"<<endl;
}


//唤醒进程
void wakeup(){
    if (blocked->next == NULL){
        printf("阻塞态已为空!!!\n");
    }
    else{
        struct PCB *T = (struct PCB*)malloc(sizeof(struct PCB));
        T = movefirst(blocked);
        add(ready,T);
        if (running == NULL){
            running =movefirst(ready);
        }
    }
}


//终止进程 
void stop(){
    if(running!=NULL)
    {
        free(running);
        running=movefirst(ready);
    }
    else
        cout<<"\t\t没有运行的进程"<<endl;
}

//展示 
void show()
{
    struct PCB *tmp;
    cout<<endl; 
    cout<<"执行队列:";
    if(running!=NULL)
        cout<<" "<<running->name;
    cout<<endl;
    cout<<"就绪队列:";
    tmp=ready->next;
    while(tmp!=NULL){
        cout<<" "<<tmp->name;
        tmp=tmp->next;
    }
    cout<<endl;
    cout<<"阻塞队列:";
    tmp=blocked->next;
    while(tmp!=NULL){
        cout<<" "<<tmp->name;
        tmp=tmp->next;
    }
    cout<<endl;
    cout<<endl;
}

//菜单 
void menu()
{
    cout<<"\t\t--------------------"<<endl;
    cout<<"\t\t1.创建进程"<<endl;
    cout<<"\t\t2.时间片到"<<endl;
    cout<<"\t\t3.阻塞进程"<<endl;
    cout<<"\t\t4.唤醒进程"<<endl;;
    cout<<"\t\t5.终止进程"<<endl;
    cout<<"\t\t6.退出程序"<<endl;
    cout<<"\t\t--------------------"<<endl;
}


main()
{
    ready=(struct PCB*)malloc(sizeof(struct PCB));
    ready->next=NULL;
    blocked=(struct PCB*)malloc(sizeof(struct PCB));
    blocked->next=NULL;
    int c;
    while(1)
    {
        menu();
        cout<<"输入功能:";
        cin>>c;
        switch(c)
        {
            case 1:
                creat();
                break;
            case 2:
                timeout();
                break;
            case 3:
                block();
                break;
            case 4:
                wakeup();
                break;
            case 5:
                stop();
                break;
            case 6:
                exit(0);
            default:
                cout<<"没有这个选项,请重新输入"<<endl;
        }
        show();
    }
}

 

posted @ 2022-06-16 18:37  王回甘  阅读(1774)  评论(0编辑  收藏  举报