C++ 多线程 模拟处理机调度

§2.1第二题实验目标
实验内容:进程调度。
模拟进程调度:按简单循环轮转调度算法模拟进程调度。
用一个队列模拟一系列(不少于5个)需要调度的进程,每个进程按照时间片进行处理机的分派,假设进程控制块PCB的结构如下:
进程ID
到达时间
进程响应时间
剩余时间
实验要求:
a)PCB内容自由指定,逻辑上合理即可(即不要求定义真正的时间,只要给出合理的数字即可);
b)时间片定义为:(所有进程总响应时间之和)/N2 (N为进程数);
c)在屏幕上输出以下进程状态表(表中每一行代表一个进程对一个时间片的占用):
进程ID 到达
时间 进程响应
时间 时间片
开始时间 时间片
结束时间

注意:到达时间为进程到达的时刻;进程响应时间是指一个进程预计占用CPU的总时间,不包括等待时间。这两个时间可视为初始条件(即在表中不会发生变化)。
d)要求可以通过键盘命令动态地增加进程(即增加一个PCB数据结构项),增加进程后,进程状态表内容可更新查看。

§2.2 第二题原理、方法、过程
2.2.1 设计思想
简单循环轮转调度的基本方法是当CPU空闲时,选取队首元素,赋予时间片。当该进程时间片用完时,就释放CPU控制权,进入就绪队列队尾,CPU交给下一个处于就绪队列队首元素。如下图所示:
在这里插入图片描述
其中,当CPU运行时,出现新的进程,则将该进程放入就绪队列,等待CPU调度,而时间片用完的进程,也可以看作一个新进程放入就绪队列进行等待。
2.2.2 程序接口设计
进程控制模块设计如下:
struct Process
{
int pos; //代表第几个输入的进程
char Process_name[50]; //进程名字,默认最长长度占用50字符
double Arrival_time; //进程到达时间
double Service_time; //服务时间 进程所需要的时间
double Start_time; //服务开始时间
double End_time; //服务结束的时间
double Turnaround_time; //周转时间 进程结束的时间-进程到达时间
}
void Init() 初始化函数,输入进程数量以及到达时间,运行时间,并且计算时间片大小
void updata() 更新就绪队列中数据,将时间片内到达的进程加入队列
void Solve_TSRA() 轮转调度算法实现

2.2.3 流程图
在这里插入图片描述
§2.3 第二题实验结果(关键的真实代码、截图、结果等)
2.3.1 代码展示

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fstream>
using namespace std;
const int MAXN = 1000;//假设能够容纳的进程最多的个数
ifstream ifile;
struct Process
{
    int pos;                          //代表第几个输入的进程
    char Process_name[50];            //进程名字,默认最长长度占用50字符
    double Arrival_time;             //进程到达时间
    double Service_time;             //服务时间       进程所需要的时间
    double Start_time;               //服务开始时间
    double End_time;                 //服务结束的时间
    double Turnaround_time;          //周转时间    进程结束的时间-进程到达时间
}process[MAXN];
double every_time;
int n;
queue<Process> que;     //就绪队列
bool vis[MAXN];      //表示这个进程有没有在完成,完成使用true表示
bool in[MAXN];       //表示这个进程是否进队列
Process ans[MAXN];  //答案序列
double time; //计时器
int index = 0;  //答案序列的指针
bool flag = false; //判断是否所有的进程都已经进队列
void Init()
{
    n = 0;
    ifile.open("process.txt");
    if (!ifile.is_open())
    {
        cout << "文件打开错误" << endl;
        exit(1);
    }
    while (!ifile.eof())
    {
        ifile >> process[n].Process_name >> process[n].Arrival_time >> process[n].Service_time;
        process[n].pos = n;
        every_time += process[n].Service_time;
        n++;
    }
    every_time /= n * n;
    every_time = ((int)(every_time * 100));
    every_time = (double)every_time / 100;
    cout << "时间片为" << every_time<<endl;
}
bool cmp1(const Process& a, const Process& b)
{
    return a.Arrival_time < b.Arrival_time;
}
void updata()
{
    int j;
    for (j = 0; process[j].Arrival_time<=time && j<n; j++) //寻找下一个进程
        if (!in[process[j].pos])
        {
            que.push(process[j]);//将时间片内到达的进程加入到队列中
            in[process[j].pos] = true;  //标记已经入就绪队列
        }
    if (j == n)
        flag = true;
}
void Solve_TSRA()
{
    sort(process, process + n-1, cmp1);
    memset(in, false, sizeof(in));
    que.push(process[0]); 
    in[process[0].pos] = true;
    time = process[0].Arrival_time;
    while (!que.empty())
    {
        Process temp = que.front();  
        que.pop();
        temp.Start_time = time;
        if (temp.Service_time > every_time)
        {
            temp.End_time = time + every_time;
            temp.Service_time -= every_time;
            time += every_time;
            updata();
            que.push(temp);
        }
        else
        {
            temp.End_time = time + temp.Service_time;
            time += temp.Service_time;       //这里面的时间都是有联系的,所以不用再次更新time
            updata();
            temp.Service_time = 0;
        }
        ans[index++] = temp;             //将顺序存储到最终的答案序列中
        if (que.empty() && !flag)
        {
            for (int i = 1; i < n; i++)
            {
                if (!in[process[i].pos])
                {
                    que.push(process[i]);
                    time = process[i].Arrival_time; //更新时间
                    break;
                }
            }
        }
    }

    printf("进程ID\t到达时间\t进程响应时间\t时间片开始时间\t时间片结束时间\n");
    for (int i = 1; i < index; i++)
        printf("%s\t%.2lf\t\t%.2lf\t\t%.2lf\t\t%.2lf\n", ans[i].Process_name, ans[i].Arrival_time, ans[i].End_time-ans[i].Start_time, ans[i].Start_time, ans[i].End_time);
    
}
int main()
{
    Init();
    Solve_TSRA();
    return 0;
}

2.3.2 运行截图
输入的进程数据如下
在这里插入图片描述
运行结果如下:
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 模拟处理机调度算法C是指将任务队列中的作业根据它们的剩余执行时间进行排序,选择剩余执行时间最短的作业来运行,从而达到最短处理时间的目的。 算法C的具体实现步骤如下: 1. 将所有的作业按照顺序加入任务队列。 2. 对于每个时间片,从任务队列中选择剩余执行时间最短的作业。 3. 运行该作业一个时间片,并更新该作业的剩余执行时间。 4. 如果该作业的剩余执行时间为0,则将该作业从任务队列中移除。 5. 重复步骤2-4,直到所有作业都被处理完。 算法C的优点是能够获得最短的处理时间,因为它总是选择剩余执行时间最短的作业来运行。这可以保证作业的响应时间和完成时间都能够得到最小化的保证。 然而,算法C也存在一些缺点。首先,它只考虑了作业的剩余执行时间,而没有考虑作业的优先级、紧迫程度等其他因素。其次,在某些情况下,算法C可能会导致某些作业长时间等待,从而降低了系统的整体效率。 综上所述,算法C是一种以最短处理时间为目标的调度算法。它虽然能够获得较短的响应时间和完成时间,但在某些情况下可能会存在效率问题。因此,在实际应用中,我们需要根据具体的场景和需求选择适合的调度算法。 ### 回答2: 模拟处理机调度算法C是一种常用的调度算法,主要针对多道程序设计环境下的处理机分配问题。该算法根据进程的优先级和执行时间确定处理机调度顺序。 具体而言,模拟处理机调度算法C的步骤如下: 1. 首先,根据进程的优先级来对进程队列进行排序,优先级高的进程排在前面。 2. 然后,根据排好序的进程队列,按照进程的优先级高低依次分配处理机。即,优先级高的进程先执行。 3. 在进程执行的过程中,根据进程的执行时间进行时间片轮转。当一个进程执行的时间达到了时间片的限制时,将处理机分配给下一个优先级最高的进程。 4. 如果有多个进程具有相同的优先级,可以采用轮流调度的方式,即每个进程轮流分配处理机,每个进程执行同样的时间片。 5. 当所有进程都执行完毕时,结束调度算法。 模拟处理机调度算法C的特点是能够保证高优先级的进程优先执行,从而可以更好地满足多道程序设计环境下的实时性要求。此外,该算法还可以避免某些低优先级进程长时间占用处理机资源,从而提高整个系统的效率。 然而,模拟处理机调度算法C也存在一些不足之处。由于优先级高的进程可能长时间占用处理机资源,可能导致其他低优先级进程的运行较慢甚至出现饥饿现象。另外,该算法没有考虑进程的响应时间,可能导致一些高优先级的进程等待时间过长。 综上所述,模拟处理机调度算法C是一种常用的调度算法,适用于多道程序设计环境。它通过优先级和执行时间的综合考虑来分配处理机资源,可以满足实时性要求,但需要注意饥饿和响应时间的问题。 ### 回答3: 模拟处理机调度算法C是一种优先级调度算法,即根据作业的优先级来确定任务的执行顺序。该算法的核心思想是通过比较作业的优先级,选择优先级最高的作业先执行,以提高处理机的利用率和系统的响应速度。 算法C的步骤如下: 1. 初始化调度队列,将所有作业按照优先级从高到低依次加入队列。 2. 从队列中选择优先级最高的作业,将其分配给处理机执行。 3. 处理机执行该作业一段时间后,检查是否有更高优先级的作业进入队列。 - 如果有,将当前作业暂停,将新作业加入队列并分配给处理机执行。 - 如果没有,继续执行当前作业,直到该作业完成或出现更高优先级的作业。 4. 重复步骤2和步骤3,直到所有作业完成。 模拟处理机调度算法C的优点是能够根据作业的优先级进行灵活调度,确保高优先级作业的及时执行,从而提高系统的性能和响应速度。然而,这种算法可能存在优先级反转的问题,即一个低优先级的长作业会阻塞高优先级的短作业,从而降低系统的效率。 为了解决优先级反转的问题,可以引入抢占式优先级调度算法,如模拟处理机调度算法P。该算法在作业进入队列时会进行实时的优先级比较,如果出现更高优先级的作业,则立即将当前作业暂停,将新作业分配给处理机执行,以保证高优先级作业的及时处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值