操作系统 实验2【动态高优先权优先调度算法 C++】

本文档详细介绍了使用C++和Python实现操作系统实验,包括短作业优先、动态高优先权优先等调度算法。实验涉及进程结构体定义、排序、状态更新、权重变化计算、周转时间和带权周转时间的计算等。实验结果展示了动态高优先权优先调度的过程,加深了对动态优先权调度算法的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 操作系统 实验1【短作业优先调度算法(C++实现——FCFS\SJF\HRRN)】
  2. 操作系统 实验2【动态高优先权优先调度算法 C++实现】
  3. 操作系统 实验3【动态分区存储管理 Python实现】
  4. 操作系统 实验4【基本分页存储管理 C++实现】

目录

一、实验目的(目的与任务)

二、实验内容(内容、要求与安排方式)

三、实验代码

①首先需要定义一个作业结构体,并在结构体内部设置状态变量

②编写按照到达时间排序的函数

③设置表示所有作业数量与单位时间权重变化的全局变量

④编写更改进程状态的函数

⑤输入实验数据(进程的各个状态量)

⑥动态高优先权优先调度算法的具体实现

⑦计算作业的各个时间值,并输出

⑧使用文件操作读取实验数据

将程序打包为exe文件

实验代码1

实验代码2

四、实验结果

五、实验总结


一、实验目的(目的与任务)

目的:了解并掌握动态高优先权优先调度算法的理论,掌握动态优先权的设置方式。

任务:模拟实现动态高优先权优先的调度(若数值越大优先权越高,每运行一个时间单位优先权-n,若数值越小优先权越高,每运行一个时间单位优先权+n)。

二、实验内容(内容、要求与安排方式)

实验学时:2            实验类型:综合型

1.实验内容与要求:

(1)实验内容

设置进程体:进程名,进程的到达时间,服务时间,初始优先权,进程状态(W——等待,R——运行,F——完成),进程间的链接指针;

进程初始化:由用户输入进程名、服务时间、初始优先权进行初始化,同时,初始化进程的状态为W;

显示函数:在进程调度前、调度中和调度后进行显示;

排序函数:对就绪状态的进程按照优先权排序。优先权相同时进入等待队列时间早的进程在前,注意考虑到达时间;

调度函数:每次从等待队列队首调度优先权最高的进程执行,状态变化。并在执行一个时间单位后优先权变化,服务时间变化,状态变化。当服务时间为0时,状态变为F;

删除函数:撤销状态为F的进程。

(2)实验要求

①测试数据可以随即输入或从文件中读入;

②必须要考虑到进程的到达时间;

③最终能够计算每一个进程的周转时间、带权周转时间。

2.实验安排方式:

上机。

3.实验设备

1.所用设备:装有C/C++/JAVA等编程环境的计算机。

2.消耗性器材:无。

三、实验代码

①首先需要定义一个作业结构体,并在结构体内部设置状态变量

struct Job // 动态高优先权优先调度

{

    int pid;

    int startTime;  //到达时间

    int readTime;   //进入准备队列的时间

    int runTime;    //运行时间

    int serverTime; //服务时间

    int status;     //0==等待,1==运行,2==完成

    int weight;     //优先权,值越大,优先权越高

    int finishTime; //完成时间

job[100001];

②编写按照到达时间排序的函数

bool cmp(Job aJob b)

{

    return a.startTime < b.startTime;

}

sort(jobjob + ncmp); //按到达时间排序(主函数调用排序函数)

③设置表示所有作业数量与单位时间权重变化的全局变量

int n; //所有作业数量

int x; //每过一个时间单位权重的变化

④编写更改进程状态的函数

void updateStatus(int idint timeint staint runint weint read) //修改进程状态

{

    for (int i = 0i < ni++)

    {

        if (job[i].pid == id)

        {

            job[i].weight = we;

            job[i].runTime = run;

            job[i].finishTime = time;

            job[i].status = sta;

            job[i].readTime = read;

            break;

        }

    }

}

⑤输入实验数据(进程的各个状态量)

printf("请输入进程数量:");

scanf("%d", &n);

printf("请依次输入进程ID、进程到达时间、进程服务时间、进程初始权重:\n");

for (int i = 0i < ni++)

{

    scanf("%d %d %d %d", &job[i].pid, &job[i].startTime, &job[i].serverTime, &job[i].weight);

    job[i].status = 0;

    job[i].runTime = 0;

    job[i].readTime = job[i].startTime;

}

printf("请输入每过一个时间单位权值的变化:");

scanf("%d", &x);

⑥动态高优先权优先调度算法的具体实现

sort(jobjob + ncmp); //按到达时间排序

Job text;                //临时队首的进程作业

int nowJob = 0;          //已经进入准备队列的进程数量

for (int i = 0;; i++)    //时间刻度,当nowJob==n && 准备队列为空时跳出循环

{

    printf("\n%d时刻:\n"i);

    for (int j = nowJobj < nj++) //如果开始时刻等于当前时刻,将作业压入准备队列

        if (job[j].startTime == i && job[i].status == 0)

            ReadQueue.push(job[j]), nowJob++, text.readTime = i;

        else

            break;

    if (!ReadQueue.empty()) //如果当前时刻准备队列不为空

    {

        text = ReadQueue.top(); //取出当前准备队列队首并移除

        ReadQueue.pop();

        //当前队首进行工作,工作一个时间单位之后,权值变化并重新进入准备队列

        text.runTime++;  //运行时间+1;

        text.status = 1; //状态设为正在运行

        printf("正在运行的进程ID%d号进程\n"text.pid);

        if (text.runTime == text.serverTime) //如果运行时间==服务时间,就结束

        {

            text.finishTime = i + 1; //完成时间

            //这里完成时间为i+1,以0时刻开始,运行一个单位,那么在这里就结束了

            //但是理论的结束时间应该为后一个时间单位,所以为i+1

            text.status = 2; //状态设为2

            text.readTime = i + 1;

            updateStatus(text.pidtext.finishTimetext.statustext.runTimetext.weighttext.readTime);

            continue; //下一时刻

        }

        else //如果没有结束

        {

            text.weight -= x; //权重减少

            text.readTime = i + 1; //重新进入队列的时间

            ReadQueue.push(text); //重新进入准备队列

            updateStatus(text.pidtext.finishTimetext.statustext.runTimetext.weighttext.readTime); //修改进程状态

        }

    }

    for (int j = 0j < nj++)

    {

        printf("id%d\t上次进入队列时刻:%d\t状态:%d\t运行时间:%d\t当前权重%d\t结束时间:%d\n"job[j].pidjob[j].readTimejob[j].statusjob[j].runTimejob[j].weightjob[j].finishTime);

    }

    if (ReadQueue.empty() && nowJob == n) //如果队列为空并且所有进程作业都已入队,说明完成

        break; //跳出循环

}

⑦计算作业的各个时间值,并输出

  1. 完成时间=开始时间+服务时间
  2. 周转时间=完成时间-到达时间
  3. 带权周转时间=周转时间/服务时间

printf("\n进程名\t到达时\t完成时\t周转时\t带权周转时\n");

double avg_sum_round_time = 0.0; //平均周转时间

double avg_sum_avg_time = 0.0;   //平均带权周转时间

for (int i = 0i < ni++)

{

    printf("%d\t%d\t%d\t%d\t%.2f\n"job[i].pidjob[i].startTimejob[i].finishTimejob[i].finishTime - job[i].startTime1.00 * (job[i].finishTime - job[i].startTime) / job[i].serverTime);

    avg_sum_round_time += (job[i].finishTime - job[i].startTime);

    avg_sum_avg_time += 1.00 * (job[i].finishTime - job[i].startTime) / job[i].serverTime;

}

printf("平均周转时间:%.2f\n"avg_sum_round_time / n);

printf("平均带权周转时间:%.2f\n"avg_sum_avg_time / n);

⑧使用文件操作读取实验数据

#include <stdio.h> // freopen函数所需头文件

freopen("C:\\Users\\lwx\\Desktop\\data.txt""r"stdin);

5
1 0 6 3
2 1 4 3
3 2 1 4
4 4 1 5
5 8 3 4
0

将程序打包为exe文件

codeblocks下 写程序,先要建立一个工程。写好程序后,选择Build(构建),在工程目录里面就有个Debug或者Release的文件夹,里面就是打包好的exe文件。

  

codeblocks生成的exe文件,打开闪一下就没了,如何解决?答:加一句暂停语句:system("pause");

解析:exe程序,就是这样的。自动退出,可以加一句暂停语句:system("pause");

实验代码1

 

//https://blog.csdn.net/weixin_44606097/article/details/106044658
#include <stdio.h>
#include <fstream>
#include <queue>
#include <algorithm>

using namespace std;

const int jobNum_Max = 10000;

struct jobInfo
{
    int uid;            //进程号
    int arrival_time;   //到达时间
    int service_time;   //服务时间
    int ready_time;     //进入就绪队列时间
    int remaining_time; //剩余服务时间
    int finish_time;    //完成时间
    int weight;         //权重
    char status;        //状态
    friend bool operator<(jobInfo a, jobInfo b)
    {
        if (a.weight == b.weight)
            return a.ready_time > b.ready_time; //时间小的优先
        return a.weight < b.weight;             //权值大的优先
    }
} job[jobNum_Max];

int in_it(); //初始化,返回作业总数
bool cmp(jobInfo a, jobInfo b);
void solve();
void updateTojob(jobInfo t);
priority_queue<jobInfo> updateToWaitList();
void Show_Before();                          //初始信息
priority_queue<jobInfo> Show_Ing(jobInfo t); //每个时刻作业的情况
void Show_After();                           //调度图

int TotalNum, CurrentTime; //作业总数量、模拟时间片前进
int WeightChange;
int record[jobNum_Max]; //每个时间片处理的作业名

priority_queue<jobInfo> WaitList;

int main()
{
    TotalNum = in_it();
    Show_Before();
    solve();
    Show_After();
}

int in_it()
{
    int flag;
    printf("请选择输入方式(控制台输入选择 1,文件输入选择 2): ");
    scanf("%d", &flag);
    while (flag != 1 && flag != 2)
    {
        printf("输入错误,请重新输入:\n");
        scanf("%d", &flag);
    }
    int n = 0;
    if (flag == 1)
    {
        printf("请按照格式输入:“进程ID 进程到达时间 进程服务时间 进程初始权重”,按“Ctrl+Z”结束输入!\n");
        while (scanf("%d%d%d%d", &job[n].uid, &job[n].arrival_time, &job[n].service_time, &job[n].weight) != EOF)
        {
            job[n].status = 'W';
            job[n].remaining_time = job[n].service_time;
            job[n].ready_time = 0;
            n++;
        }
    }
    else
    {
        ifstream date;
        date.open("date.txt");
        while (!date.eof())
        {
            date >> job[n].uid >> job[n].arrival_time >> job[n].service_time >> job[n].weight;
            job[n].status = 'W';
            job[n].remaining_time = job[n].service_time;
            job[n].ready_time = 0;
            n++;
        }
        printf("数据读取成功!\n");
    }
    sort(job, job + n, cmp);
    printf("请输入每过一个时间单位权值的变化:");
    scanf("%d", &WeightChange);
    return n;
}

bool cmp(jobInfo a, jobInfo b)
{
    return a.arrival_time < b.arrival_time;
}

void solve()
{
    int InJobNum = 0;
    jobInfo Running;
    Running.uid = -1;
    while (InJobNum != TotalNum || !WaitList.empty())
    {
        for (int i = InJobNum; i < TotalNum; i++)
        {
            if (job[i].arrival_time == CurrentTime)
            {
                job[i].ready_time = CurrentTime;
                WaitList.push(job[i]);
                InJobNum++;
            }
            else
                break;
        }
        if (!WaitList.empty())
        {
            Running = WaitList.top();
            WaitList.pop();
            Running.status = 'R';
            WaitList = Show_Ing(Running);
            Running.remaining_time--;
            record[CurrentTime++] = Running.uid;
            if (!Running.remaining_time)
            {
                Running.finish_time = CurrentTime;
                Running.status = 'F';
                updateTojob(Running);
            }
            else
            {
                Running.weight -= WeightChange;
                Running.ready_time = CurrentTime;
                Running.status = 'W';
                WaitList.push(Running);
                updateTojob(Running);
            }
        }
        else
        {
            Running.uid = -1;
            WaitList = Show_Ing(Running);
            record[CurrentTime++] = -1;
        }
        //WaitList = updateToWaitList();
    }
    Running.uid = -1;
    WaitList = Show_Ing(Running);
}

void updateTojob(jobInfo t)
{
    for (int i = 0; i < TotalNum; i++)
    {
        if (job[i].uid == t.uid)
        {
            job[i] = t;
            return;
        }
    }
}

priority_queue<jobInfo> updateToWaitList()
{
    priority_queue<jobInfo> t;
    while (!WaitList.empty())
    {
        jobInfo a = WaitList.top();
        WaitList.pop();
        a.weight += WeightChange;
        t.push(a);
        updateTojob(a);
    }
    return t;
}

void Show_Before()
{
    putchar('\n');
    printf("%s\n", "进程信息");
    printf("%s\t%s\t%s\t%s\n", "Id", "arrival", "service", "weight");
    for (int i = 0; i < TotalNum; i++)
        printf("%d\t%d\t%d\t%d\n", job[i].uid, job[i].arrival_time, job[i].service_time, job[i].weight);
}

priority_queue<jobInfo> Show_Ing(jobInfo t)
{
    priority_queue<jobInfo> Temp;
    putchar('\n');
    printf("%s\t%s\t%s\t%s\t%s\t%s=%d\n", "Id", "remain", "status", "weight", "ready", "Time", CurrentTime);
    if (t.uid != -1)
        printf("%d\t%d\t%c\t%d\t%d\n", t.uid, t.remaining_time, t.status, t.weight, t.ready_time);
    while (!WaitList.empty())
    {
        jobInfo a = WaitList.top();
        WaitList.pop();
        printf("%d\t%d\t%c\t%d\t%d\n", a.uid, a.remaining_time, a.status, a.weight, a.ready_time);
        Temp.push(a);
    }
    for (int i = 0; i < TotalNum; i++)
        if (job[i].status == 'F')
            printf("%d\t%d\t%c\t%d\n", job[i].uid, job[i].remaining_time, job[i].status, job[i].weight);
    return Temp;
}

void Show_After()
{
    putchar('\n');
    printf("结果详情\n");
    printf("%s\t%s\t%s\t%s\t%s\t%s\n", "Name", "Arrival", "Finish", "Service", "cycling", "W=T/Ts");
    for (int i = 0; i < TotalNum; i++)
    {
        jobInfo t = job[i];
        int zz = t.finish_time - t.arrival_time;
        printf("%d\t%d\t%d\t%d\t%d\t%.2lf\n", t.uid, t.arrival_time, t.finish_time, t.service_time, zz, 1.0 * zz / t.service_time);
    }
    putchar('\n');
    printf("动态 高优先权优先调度算法 时间图\n\t|");
    for (int i = 0; i <= CurrentTime; i++)
        printf("%-4d", i);
    putchar('\n');
    for (int i = 0; i < TotalNum; i++)
    {
        printf("%d\t|", job[i].uid);
        for (int j = 0; j < CurrentTime; j++)
        {
            if (job[i].uid == record[j])
                printf("——");
            else
                printf("    ");
        }
        putchar('\n');
    }
}
/*
1 0 5 3
2 1 4 3
3 2 1 5
4 4 2 4
5 5 1 5

1 0 5 3
2 1 3 5
3 2 1 3
4 3 1 4
5 4 2 2

1 0 6 3
2 1 4 3
3 2 1 4
4 4 1 5
5 8 3 4
*/

实验代码2

#include <stdio.h> // freopen函数所需头文件
#include <bits/stdc++.h>

using namespace std;

struct Job //动态高优先权优先调度算法
{
    int pid;
    int startTime;  //到达时间
    int readTime;   //进入准备队列的时间
    int runTime;    //运行时间
    int serverTime; //服务时间
    int status;     //0==等待,1==运行,2==完成
    int weight;     //优先权,值越大,优先权越高
    int finishTime; //完成时间
} job[100001];

int n; //所有作业数量
int x; //每过一个时间单位权重的变化

bool operator<(const Job &a, const Job &b) //结构体重载函数
{
    if (a.weight == b.weight)
        return a.readTime > b.readTime; //优先权相等,更早进入准备队列的优先
    return a.weight < b.weight;
}

bool cmp(Job a, Job b)
{
    return a.startTime < b.startTime;
}

priority_queue<Job> ReadQueue; //进程准备队列

void updateStatus(int id, int time, int sta, int run, int we, int read) //修改进程状态
{
    for (int i = 0; i < n; i++)
    {
        if (job[i].pid == id)
        {
            job[i].weight = we;
            job[i].runTime = run;
            job[i].finishTime = time;
            job[i].status = sta;
            job[i].readTime = read;
            break;
        }
    }
}

int main()
{
    // freopen("C:\\Users\\lwx\\Desktop\\data.txt", "r", stdin); //使用文件操作读取实验数据
    freopen("data.txt", "r", stdin); //使用文件操作读取实验数据
    printf("请输入进程数量:");
    scanf("%d", &n);
    printf("请依次输入进程ID、进程到达时间、进程服务时间、进程初始权重:\n");
    for (int i = 0; i < n; i++)
    {
        scanf("%d %d %d %d", &job[i].pid, &job[i].startTime, &job[i].serverTime, &job[i].weight);
        job[i].status = 0;
        job[i].runTime = 0;
        job[i].readTime = job[i].startTime;
    }
    printf("请输入每过一个时间单位权值的变化:");
    scanf("%d", &x);
    sort(job, job + n, cmp); //按到达时间排序
    Job text;                //临时队首的进程作业
    int nowJob = 0;          //已经进入准备队列的进程数量
    for (int i = 0;; i++)    //时间刻度,当nowJob==n && 准备队列为空时跳出循环
    {
        printf("\n第%d时刻:\n", i);
        for (int j = nowJob; j < n; j++) //如果开始时刻等于当前时刻,将作业压入准备队列
            if (job[j].startTime == i && job[i].status == 0)
                ReadQueue.push(job[j]), nowJob++, text.readTime = i;
            else
                break;
        if (!ReadQueue.empty()) //如果当前时刻准备队列不为空
        {
            text = ReadQueue.top(); //取出当前准备队列队首并移除
            ReadQueue.pop();
            //当前队首进行工作,工作一个时间单位之后,权值变化并重新进入准备队列
            text.runTime++;  //运行时间+1;
            text.status = 1; //状态设为正在运行
            printf("正在运行的进程ID:%d号进程\n", text.pid);
            if (text.runTime == text.serverTime) //如果运行时间==服务时间,就结束
            {
                text.finishTime = i + 1; //完成时间
                //这里完成时间为i+1,以0时刻开始,运行一个单位,那么在这里就结束了
                //但是理论的结束时间应该为后一个时间单位,所以为i+1
                text.status = 2; //状态设为2
                text.readTime = i + 1;
                updateStatus(text.pid, text.finishTime, text.status, text.runTime, text.weight, text.readTime);
                continue; //下一时刻
            }
            else //如果没有结束
            {
                text.weight -= x;                                                                               //权重减少
                text.readTime = i + 1;                                                                          //重新进入队列的时间
                ReadQueue.push(text);                                                                           //重新进入准备队列
                updateStatus(text.pid, text.finishTime, text.status, text.runTime, text.weight, text.readTime); //修改进程状态
            }
        }
        for (int j = 0; j < n; j++)
        {
            printf("id:%d\t上次进入队列时刻:%d\t状态:%d\t运行时间:%d\t当前权重%d\t结束时间:%d\n", job[j].pid, job[j].readTime, job[j].status, job[j].runTime, job[j].weight, job[j].finishTime);
        }
        if (ReadQueue.empty() && nowJob == n) //如果队列为空并且所有进程作业都已入队,说明完成
            break;                            //跳出循环
    }

    printf("\n进程名\t到达时\t完成时\t周转时\t带权周转时\n");
    double avg_sum_round_time = 0.0; //平均周转时间
    double avg_sum_avg_time = 0.0;   //平均带权周转时间
    for (int i = 0; i < n; i++)
    {
        printf("%d\t%d\t%d\t%d\t%.2f\n", job[i].pid, job[i].startTime, job[i].finishTime, job[i].finishTime - job[i].startTime, 1.00 * (job[i].finishTime - job[i].startTime) / job[i].serverTime);
        avg_sum_round_time += (job[i].finishTime - job[i].startTime);
        avg_sum_avg_time += 1.00 * (job[i].finishTime - job[i].startTime) / job[i].serverTime;
    }
    printf("平均周转时间:%.2f\n", avg_sum_round_time / n);
    printf("平均带权周转时间:%.2f\n", avg_sum_avg_time / n);

    system("pause");
    return 0;
}
/*
5
1 0 6 3
2 1 4 3
3 2 1 4
4 4 1 5
5 8 3 4
0
*/

四、实验结果

实验代码2

五、实验总结

动态高优先权优先调度算法的基本原理:

1.基本思想:为每个进程设置一个优先级,在调度的时候,选取优先级最大的任务去执行。

2.优先级可以是静态赋予:创建任务的时候,就指定优先级大小,并且保持不变,直到任务结束;也可以是动态赋予:优先级在执行任务中动态改变。

4.为了防止高优先级进程无休止地运行下去,程序可以在每个时钟中断时,降低当前进程的优先级。

5.在平时,可以把不同的任务划分为不同的优先级,然后在相同优先级的任务中使用时间片轮转。

本实验是模拟动态高优先权优先调度算法(抢占式)实现处理机调度的程序,实验中假设所有创建的进程都已在内存中,即一个等待运行的队列中,每次都将优先级最高的进程放到队首,然后每运行一次进程就降低一个单位的优先权再进行优先权比较;如果优先级相同则比较到达时间,将优先级最高且到达时间最早的进程放到队首。若出现优先权更高的进程,则立即停止当前正在执行的进程,并将处理机分配给新到达的优先权最高的进程。

动态优先数是指在进程创建时先确定一个初始优先数,以后在进程运行中随着进程特性的改变而不断修改优先数。这样,由于在开始时刻优先数很低而得不到CPU的进程,就能因为等待时间的增长而优先数变高从而得到CPU使用权,增加CPU利用率。动态调度,虽然有足够的灵活性变化的系统情况,但是却需要消耗更多的系统资源。

通过此次实验,我对动态高优先权优先调度算法有了更深的理解,知道了进程调度算法的实现过程和程序编写。对作业的完成时间、周转时间、带权周转时间的计算掌握地更加熟练。实验中,将理论和实践相结合,我对操作系统的学习更加深入。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

upward337

谢谢老板~

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

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

打赏作者

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

抵扣说明:

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

余额充值