C语言 操作系统 进程控制

一、进程控制

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

内容

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

数据结构

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

typedef struct PCB{
	int num;
	int start;//基址
	int lenth;//长度
	struct PCB *next;
}PCB;
//内存空间结构体
typedef struct Space{
	int type;//0为空,1为被占
	int start;
	int length;
	struct Space *prev;
	struct Space *next;
}Space;

算法设计及流程图

建立3个PCB链表,分别存储就绪态队列、运行态队列、阻塞态队列;创建进程,采用尾插法创建就绪态,并开辟内存空间,敲入运行指令,取就绪态的头,将头插入到运行态队列中(运行态仅可有一个),敲入阻塞指令,运行态进入阻塞态,并查看就绪态是否存在节点,存在即插入到运行态;敲入唤醒指令,取阻塞头,添加到就绪队列尾部;敲击运行结束指令,运行态为空,归还空间,并将存在就绪态转换为运行态。
在这里插入图片描述

代码如下:

#include <stdio.h>
#include <stdlib.h>
typedef struct PCB{
    int num;
    int start;//基址
    int lenth;//长度
    struct PCB *next;
}PCB;
typedef struct Space{
    int type;//0为空,1为被占
    int start;
    int length;
    struct Space *prev;
    struct Space *next;
}Space;
PCB *head1 = NULL,*head2 = NULL,*head3 = NULL;
int m,n;//定义开辟的空间,基址和长度
Space *head = NULL;

int findArea(int length)
{
    int min=10000;//最小剩余量
    Space *p = head;
    Space *flag;
    do
    {
        if((p->length - length)<min&&(p->length - length)>=0&&p->type==0)
        {
            min = p->length - length;
            flag = p;
        }
        p = p->next;
    }while(p!=NULL);
    if(min<=2&&min>=0)//产生碎片
    {
        flag->type = 1;
    }
    if(min>2)//分裂原来空间
    {
        Space *s = (Space *)malloc(sizeof(Space));//更新后的空白区
        s->length = min;
        s->start = flag->start+length;
        s->prev = flag;
        s->type = 0;
        s->next = flag->next;
        flag->length = length;
        flag->type = 1;
        flag->next = s;
    }
    return flag->start;
}
//创建进程
void creat()
{
    int num;
    //int start;//基址
    int lenth;//长度
    PCB *q = head1;
    printf("请输入进程id和长度\n");
    scanf("%d %d",&num,&lenth);
    PCB *p=(PCB *)malloc(sizeof(PCB));
    p->num = num;
    p->start = findArea(lenth);
    p->lenth = lenth;
    p->next = NULL;
    if(head1 == NULL)
    {
        head1 = p;
    }
    else
    {
        while(q->next != NULL)
        {
            q = q->next;
        }
        q->next = p;
    }
}
void show()
{
    int a;
    scanf("%d",&a);
    PCB *p1,*p2,*p3;
    if(a==1)
    {
        printf("就绪态:");
        p1 = head1;
        p2 = head2;
        p3 = head3;
        while(p1!=NULL)
        {
            printf("%d(%d,%d); ",p1->num,p1->start,p1->lenth);
            p1 = p1->next;
        }
        printf("\n");
        printf("执行态:");
        while(p2!=NULL)
        {
            printf("%d(%d,%d); ",p2->num,p2->start,p2->lenth);
            p2 = p2->next;
        }
        printf("\n");
        printf("阻塞态:");
        while(p3!=NULL)
        {
            printf("%d(%d,%d); ",p3->num,p3->start,p3->lenth);
            p3 = p3->next;
        }
        printf("\n");
    }
    if(a==2)
    {
        Space *p = head;
        printf("空闲区有:\n");
        while(p!=NULL)
        {
            if(p->type==0)
            {
                printf("(%d,%d)\n",p->start,p->length);
            }
            p = p->next;
        }
    }
}
void run()
{
    if(head2!=NULL)
    {
        printf("正在有其他进程运行\n");
    }
    else
    {
        PCB *q = head1;
        head1 = head1->next;
        q->next = NULL;
        head2 = q;
    }
}
void block()
{
    PCB *q = head2;//取运行态
    head2 = NULL;
    PCB *p=head3;//加入到阻塞态
    if(head3 == NULL)
    {
        head3 = q;
    }
    else
    {
        while(p->next != NULL)
        {
            p = p->next;
        }
        p->next = q;
    }
    if(head1!=NULL)//如果就绪态不空
    {
        run();
    }
}
void success()
{

    PCB *q = head2;//取运行态
    Space *p = head;
    while(p!=NULL)
    {
        if(p->start==q->start)//查找运行态的空间
        {
            break;
        }
        p = p->next;
    }
    //3块
    if(p->prev!=NULL&&p->next!=NULL)
    {
        if(p->prev->type==1&&p->next->type==1)//1.上占下占
        {
            p->type = 0;
        }
        if(p->prev->type==1&&p->next->type==0)//2.上占下空
        {
            p->prev->next = p->next;
            p->next->start = p->start;
            p->next->length = p->length+p->next->length;
            p->next->prev = p->prev;
            free(p);
        }
        if(p->prev->type==0&&p->next->type==1)//3.上空下占
        {
            p->prev->length = p->prev->length+p->length;
            p->prev->next = p->next;
            p->next->prev = p->prev;
            free(p);
        }
        if(p->prev->type==0&&p->next->type==0&&p->next->next!=NULL)//4.上空下空 下下存在
        {
            p->prev->length = p->prev->length+p->length+p->next->length;
            p->prev->next = p->next->next;
            p->next->next->prev = p->prev;
            free(p);
            free(p->next);
        }
        if(p->prev->type==0&&p->next->type==0&&p->next->next==NULL)//5.上空下空 下下不存在
        {
            p->prev->length = p->prev->length+p->length+p->next->length;
            p->prev->next = NULL;
            free(p);
            free(p->next);
        }
    }
    //2块
    if(p->next==NULL&&p->prev!=NULL)//1.p为尾
    {
        if(p->prev->type==1)//上占
        {
            p->type = 0;
        }
        if(p->prev->type==0)//上空
        {
            p->prev->length = p->prev->length+p->length;
            p->prev->next = NULL;
        }
    }
    if(p->prev==NULL&&p->next!=NULL)//2.p为头
    {
        if(p->next->type==1)//下占
        {
            p->type = 0;
        }
        if(p->next->type==0)//下空
        {
            p->next->length = p->length+p->next->length;
            p->next->prev = NULL;
            p->next->start = p->start;
            head = p->next;
            free(p);
        }
    }
    head2 = NULL;

    if(head1!=NULL)//如果就绪态不空
    {
        run();
    }
}
void week()
{
    PCB *q = head3;//取阻塞态
    head3 = head3->next;
    PCB *p=head1;//加入到就绪态
    if(head1 == NULL)
    {
        head1 = q;
    }
    else
    {
        while(p->next != NULL)
        {
            p = p->next;
        }
        p->next = q;
    }
}
void timeSlice()
{
    PCB *q = head1;
    PCB *p = head2;//取运行态
    head2 = NULL;
    if(head1 == NULL)//将运行态添加到就绪态
    {
        head1 = p;
    }
    if(head1!=NULL)
    {
        while(q->next != NULL)
        {
            q = q->next;
        }
        q->next = p;
    }
    if(head1!=NULL)//如果就绪态不空
    {
        run();
    }
}
int main()
{
    int flag = 1;
    char a;
    printf("请输入开辟的内存空间的基址和长度\n");
    scanf("%d %d",&m,&n);
    head=(Space *)malloc(sizeof(Space));
    head->start = m;
    head->length = n;
    head->prev = NULL;
    head->next = NULL;
    head->type = 0;//0为空,1 为占用
    printf("1.创建:c+进程id+长度\n");
    printf("2.终止:e 结束正在运行的进程\n");
    printf("3.时间片到:t:将运行的进程装入就绪队列尾部,将下一个自动调度过来.\n");
    printf("4.阻塞:b 将正在执行的程序阻塞,即插入阻塞队列尾部.\n");
    printf("5.唤醒:w 将阻塞队列中的一个进程调度到就绪队列上,即阻塞队列头到就绪队列尾\n");
    printf("6.查看:随时查看队列的情况:s 1/2(s 1:查看的是三个进程队列的情况,s 2:查看的是剩余内存的情况)\n\n");

    while(flag == 1)
    {
        printf("请输入操作指令\n");
        scanf(" %c",&a);
        switch(a)
        {
            case 'c':
                creat();
                break;
            case 'r':
                run();
                break;
            case 'b':
                block();
                break;
            case 's':
                show();
                break;
            case 'e'://运行完成
                success();
                break;
            case 'w':
                week();
                break;
            case 't'://时间片倒
                timeSlice();
                break;
            case 'q':
                flag  = 0;
                break;
        }
    }

    return 0;
}

运行截图

创建3个进程实现截图
图1-2 创建3个进程实现截图
在这里插入图片描述

图1-3 阻塞、运行结束、唤醒实现截图
在这里插入图片描述

图1-4 运行结束,归还空间实现截图

  • 14
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木子Link

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值