操作系统 进程调度PCB (C++)

一、实验目的
在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实验模拟在单处理器情况下的处理器调度,帮助学生加深了解处理器调度的工作。
二、实验要求
1.设计一个按时间片轮转法实现处理器调度的程序,每个程序由一个PCB表示。
2.程序执行中应能在屏幕上显示出各进程的状态变化,以便于观察调度的整个过程。
三、实验原理
(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表。进程控制块的格式为:
进程名
指针
要求运行时间
已运行时间
状态
其中,进程名——作为进程的标识,假设五个进程的进程名分别为Q1,Q2,Q3,Q4,Q5。
指针——进程按顺序排成循环队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程的指针指出第一个进程的进程控制块首地址。
要求运行时间——假设进程需要运行的单位时间数。
已运行时间——假设进程已经运行的单位时间数,初始值为“0”。
状态——有两种状态,“就绪”和“结束”,初始状态都为“就绪”,用“R”表示。当一个进程运行结束后,它的状态为“结束”,用“E”表示。
(2) 每次运行所设计的处理器调度程序前,为每个进程任意确定它的“要求运行时间”。
(3) 把五个进程按顺序排成循环队列,用指针指出队列连接情况。另用一标志单元记录轮到运行的进程。例如,当前轮到P2执行,则有:
标志单元
K2K1	Q1	 K2	Q2	 K3	Q3	 K4	Q4	 K5	Q5K2		K3		K4		K5		K12		3		1		2		41		0		0		0		0R		R		R		R		RPCB1		PCB2		PCB3		PCB4		PCB5

(4) 处理器调度总是选择标志单元指示的进程运行。由于本实验是模拟处理器调度的功能,所以,对被选中的进程并不实际的启动运行,而是执行:
已运行时间+1
来模拟进程的一次运行,表示进程已经运行过一个单位的时间。
请同学注意:在实际的系统中,当一个进程被选中运行时,必须置上该进程可以运行的时间片值,以及恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行满一个时间片。在这时省去了这些工作,仅用“已运行时间+1”来表示进程已经运行满一个时间片。
(5) 进程运行一次后,应把该进程的进程控制块中的指针值送到标志单元,以指示下一个轮到运行的进程。同时,应判断该进程的要求运行时间与已运行时间,若该进程的要求运行时间已运行时间,则表示它尚未执行结束,应待到下一轮时再运行。若该进程的要求运行时间=已运行时间,则表示它已经执行结束,应指导它的状态修改成“结束”(E)且退出队列。此时,应把该进程的进程控制块中的指针值送到前面一个进程的指针位置。
(6) 若“就绪”状态的进程队列不为空,则重复上面的(4)和(5)的步骤,直到所有的进程都成为“结束”状态。
(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次选中进程的进程名以及运行一次后进程队列的变化。
(8) 为五个进程任意确定一组“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中的进程名以及进程控制块的动态变化过程。
实现代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#pragma warning(disable:4996)
using namespace std;
class PCB                //PCB类,包含time、range、state、next指针
{
public:
    void In(char* n, int t, int r);
    PCB()
    {
    }
    PCB(PCB* p)                //复制PCB
    {
        strcpy(name, p->name); //若str1 = str2,则返回零;若str1 > str2,则返回正数;若str1 < str2,则返回负数
        next = p->next;
        time = p->time;
        range = p->range;
        state = p->state;
    }
    void Red()                    //模拟进程运行状态
    {
        time--;
        range--;
        if (!time)
            state = 0;
    }
    void print()            //输出当前PCB内容
    {
        cout << name << "\t" << time << "\t" << range << "\t" << state << endl;
    }
    char name[10];        //进程名称
    PCB* next;            //用于链表的指针
    int time;            //用于记录进程运行时间
    int range;            //用于记录优先值
    int state;            //用于判断该进程是否运行结束
};

void PCB::In(char* n, int t, int r)  //初始化PDB对象
{
    strcpy(name, n);
    time = t;
    range = r;
    next = NULL;
    if (t > 0)
        state = 1;
    else
        state = 0;
}
void Pri_Li(PCB* head)            //用于输出每一次运行的结果
{
    if (head)
    {
        cout << "进程队列为:";
        for (; head; head = head->next)
            cout << head->name << ",";
    }
    else
        cout << "进程已全部运行完毕。" << endl;
    cout << endl;
}

void Grp(PCB*& head, PCB* p, int num)//用于队列的排序,num为当前队列中存在的指针个数
{
    int ii = num;
    if (p->state)            //当该对象为新进程是,插入队列
    {
        if (!num)
        {
            head = p;
            (head)->next = NULL;
        }
        else
        {
            PCB* tp = head;
            PCB* tp2 = head;
            for (; num > 0; num--)
            {
                if (p->range > tp->range && ii == num)//位于头部插入
                {
                    p->next = head;
                    head = p;
                    break;
                }
                else if (p->range > tp->range)//位于中间插入
                {
                    p->next = tp;
                    tp2->next = p;
                    break;
                }
                else
                {
                    tp2 = tp;
                    tp = tp->next;
                }
            }
            if (!num && !tp)//位于尾部插入
            {
                tp2->next = p;
            }

        }
    }
    else                    //当该对象是已完成进程时,从队列中除去
    {
        PCB* tp = head;
        int tem = num;
        for (PCB* tp2 = tp; num > 0; num--, tp = tp->next)
        {
            if (!strcmp(p->name, tp->name) && tem == num)
            {
                head = head->next;
                break;
            }
            else if (!strcmp(p->name, tp->name))
            {
                tp2->next = tp->next;
                break;
            }
            else
                tp2 = tp;
        }

    }
}
void Pro(PCB*& p, int sum)   //模拟进程运行,并重新排序队列
{
    PCB* k, * pk;
    int i;
    for (; sum;)
    {
        k = p;
        p->Red();
        cout << "此次运行了进程" << p->name << "剩余时间" << p->time << "权值" << p->range << endl;
        if (!k->state)
        {
            Grp(p, k, sum);
            sum--;
        }
        else if (sum == 1)
            continue;
        else
        {
            pk = k = k->next;
            for (i = sum - 1; i > 0; i--)
            {
                if (p->range >= k->range && i == sum - 1)//ok
                {
                    break;
                }
                else if (p->range >= k->range)
                {
                    pk->next = p;
                    p = p->next;
                    pk->next->next = k;
                    break;
                }
                pk = k;
                k = k->next;
            }
            if (!i && !k)
            {
                pk->next = p;
                p = p->next;
                pk->next->next = NULL;
            }

        }
        Pri_Li(p);
    }
}
int main()
{
    int num, sum, t, r;
    char n[10];
    cout << "这是一个模拟系统加权进程调度程序" << endl
        << "请输入总的进程数:";
    cin >> sum;
    PCB* PP[5];
    PCB* head;
    for (int i = 0; i < sum; i++)
    {
        PP[i] = new PCB;
        cout << "请输入进程名称、进程运行时间、进程优先数:";
        cin >> n;

        cin >> t;

        cin >> r;
        PP[i]->In(n, t, r);
        num = i;
        Grp(head, PP[i], num);
    }
    Pro(head, sum);
    getchar();
    return 0;
}

控制台输入如下:
进程名任意;进程运行时间为该进程完成所需时间;优先数(权值)越大越先执行
在这里插入图片描述
主要思路:单处理器系统时间片为1的进程调度,只需要考虑其权值以及进程剩余时间。
不足:未考虑时间片不为1的情况。

  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程调度算法模拟。通过对进程调度算法的模拟,进一步理解进程的基本概念,加深对进程运行状态和进程调度过程、调度算法的理解。 (1) 用C、C++、Java语言编程实现对5个进程采用动态优先权调度算法进行调度的过程。数据如下: 5个进程的到达时刻和服务时间见下表,忽略I/O以及其它开销时间,使用动态优先权算法进行调度,优先权初始值为100,请输出各个进程的完成时刻、周转时间、带权周转时间。 进程 到达时刻 服务时间 A 0 3 B 2 6 C 4 4 D 6 5 E 8 2 (2)每个用来标识进程进程控制块PCB可用结构来描述,包括以下字段(用不到的字段可以不定义)。  进程标识数ID。  进程优先数PRIORITY,并规定优先数越大的进程,其优先权越高。  进程已占用CPU时间CPUTIME。  进程还需占用的CPU时间ALLTIME。当进程运行完毕时,ALLTIME变为0。  进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK个时间片后,进程将进入阻塞状态。  进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待BLOCKTIME个时间片后,将转换成就绪状态。  进程状态STATE。  队列指针NEXT,用来将PCB排成队列。 (3)优先数改变的原则:  进程在就绪队列中呆一个时间片,优先数增加1。  进程每运行一个时间片,优先数减3。 (4)为了清楚地观察每个进程调度过程,程序应将每个时间片内的进程的情况显示出来,包括正在运行的进程,处于就绪队列中的进程和处于阻塞队列中的进程。 (5)分析程序运行的结果,谈一下自己的认识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值