高响应比优先调度和时间片轮转进程调度算法(C++代码及文档)

一、实验目的

通过编写实现高响应比优先(HRRN)调度和时间片轮转(RR)调度算法的程序,深刻理解复杂的进程调度机制,掌握其算法实现的过程。通过模拟调度过程,计算每个进程的周转时间和带权周转时间,进一步提升对进程调度性能分析的能力,为系统级编程提供实践经验。

二、需求分析

2.1 程序设计任务

该程序旨在实现两种经典的进程调度算法——高响应比优先(HRRN)调度算法和时间片轮转(RR)调度算法的模拟过程,并通过计算各个进程的完成时间、周转时间、带权周转时间,得出平均周转时间和平均带权周转时间,以辅助用户深入理解这两种进程调度算法的过程及特点。

2.2 输入内容、形式范围

1. 进程个数 n:

  • 输入内容:正整数,表示有 n 个进程参与调度;
  • 输入形式:用户通过键盘为程序输入单一正整数;
  • 输入范围:1 ≤ n ≤ 10,000(1e4)。

  1. 每个进程的到达时间 (arrivalTime):
  • 输入内容:表示进程到达系统的时间;
  • 输入形式:非负整数;
  • 输入范围:0 ≤ arrivalTime。

  1. 每个进程的服务时间 (serviceTime):
  • 输入内容:每个进程需要的服务时间;
  • 输入形式:正整数;
  • 输入范围:1 ≤ serviceTime。

  1. 选择调度算法:
  • 输入内容:

1 对应高响应比优先(HRRN)调度;

2 对应时间片轮转(RR)调度。

  • 输入形式:单一整数;
  • 输入范围:仅限整数1或2。

2.3 输出形式

  • 模拟调度过程,输出每个进程的运行情况,例如:时刻3:进程2开始运行
  • 每个进程的输出:完成时间、周转时间、带权周转时间
  • 总体:平均周转时间、平均带权周转时间

2.4 测试数据

2.4.1 正确的输入

2.4.2 错误的输入

  1. 进程数超过1e4

  1. 到达时间低于0

  1. 服务时间不为正整数

  1. 调度算法选择错误

三、概要设计

3.1 抽象数据类型的定义

1. struct BankersAlgorithm 数据类型

  • 用于表示一个进程的相关属性,包括:
  • id: 进程标识(从1开始)。
  • arrivalTime: 该进程的到达时间。
  • serviceTime: 该进程需要的服务时间。
  • remainingTime: 剩余服务时间(用于RR算法)。
  • finishTime: 进程的完成时间。
  • wholeTime: 进程的周转时间。
  • weightedWholeTime: 进程的带权周转时间。
  • flag: 标识此进程是否已进入调度队列(用于RR算法)。

2. 辅助变量及数据结构

  • currentTime: 当前的系统时钟时间。
  • finished: 一个布尔数组,记录每个进程是否已完成,适用于HRRN算法。
  • queue<int> readyQueue: 一个队列,保存处于就绪状态的进程在RR算法中的顺序。

3.2 主程序流程

主程序主要流程如下:

1.输入阶段

  • 输入进程数量和每个进程的到达时间、服务时间。
  • 选择调度算法:
  • 如果选择时间片轮转法(RR),还需输入时间片大小。

2.算法处理阶段

根据用户选择,调用HRRN算法或RR算法,完成进程调度的模拟。包括:

  • 输出调度过程的动态信息(进程开始运行和完成运行的时刻)。
  • 计算完成时间、周转时间和带权周转时间。

3.结果统计阶段

  • 计算所有进程的平均周转时间和平均带权周转时间。
  • 输出各进程的相关调度信息(完成时间、周转时间和带权周转时间),以及平均统计结果。

四、详细设计

4.1 高响应比优先(HRRN)调度算法实现

1. 初始化当前时间currentTime为0,维护未完成进程的列表。

2. 在当前时刻,从所有满足到达条件的未完成进程中选择响应比最高的进程。

3. 调度该进程运行,更新进程的完成时间、周转时间和带权周转时间。

4. 如果没有可执行的进程,currentTime自增等待。

5. 重复上述步骤直至所有进程完成。

4.2 时间片轮转(RR)调度算法实现

1. 初始化就绪队列readyQueue,初始时将到达时间为0的进程加入队列。

2. 从队列中依次取出进程,根据时间片大小运行。

3. 若进程未完成,在运行后再次加入队列。

4. 若进程完成,更新其完成时间、周转时间和带权周转时间,记录完成状态。

5. 若当前队列为空,等待至下一个有进程到来的时间。

6. 重复上述步骤直至所有进程完成。

4.3 计算所有进程的平均时间

对所有进程的周转时间与带权周转时间进行累加,计算平均值。

五、调试分析

5.1 调试过程中遇到的问题及解决方案

问题描述: 在时间片轮转(RR)调度算法中,进程到达时间的判断逻辑存在缺陷,导致某些进程未能及时加入就绪队列。

原因: 在空闲时刻(无进程可以运行)未正确检查所有进程的到达时间,导致可能遗漏可调度进程的入队操作。

解决方案: 当就绪队列为空时,增加一个循环检查所有未完成的进程,并将到达时间符合条件的进程加入到就绪队列。

5.2 算法的时空复杂度分析

5.2.1 算法时间复杂度分析

(1) 高响应比优先调度(HRRN)算法

  • 查找响应比最高的进程:对当前时间点下所有未完成的进程进行遍历,计算每个进程的响应比。假设有n个进程,此操作的时间复杂度为O(n)。
  • 调度下一个进程:根据计算出的响应比,选择响应比最高的进程进行调度,这属于简单的比较操作,时间复杂度为O(1)。
  • 重复调度:由于每个进程都需要被调度运行一次,因此在总的最坏情况中,HRRN调度算法需要遍历所有未完成的进程n次。

总时间复杂度: 在最坏情况下,HRRN的时间复杂度为O(n^2)。

(2) 时间片轮转(RR)算法

  • 就绪队列维护: 在每个时刻,将到达当前时间的进程加入就绪队列。此操作需要遍历所有未完成的进程,时间复杂度为O(n)。
  • 队列调度与时间片操作: 从就绪队列中取出一个进程运行,一个时间片完成后决定是继续运行还是将其重新加入队列,操作与队列长度相关,时间复杂度为O(1)。
  • 重复调度: 假设有n个进程,总的时间为T,在最坏情况下,每次运行一个时间片,进程可能循环多次。这里的时间复杂度可以表示为O(n*T/q),其中q为时间片大小。

总时间复杂度: RR算法的总时间复杂度为O(n*T/q)。

5.2.2 空间复杂度分析

进程数据结构存储: 无论是HRRN还是RR算法,都需要为每个进程额外存储其arrivalTime、serviceTime、remainingTime等字段,因此空间复杂度为O(n)。

辅助数据结构:

  • HRRN算法使用布尔数组(finished)来标记进程是否完成,其空间复杂度为O(n)。
  • RR算法使用就绪队列(readyQueue)存储所有处于就绪状态的进程,空间复杂度为O(n)。
  • 临时变量: 包括currentTime、运行中间状态等,这些变量的空间复杂度为O(1)。

总空间复杂度: O(n)。

5.2.3 改进设想

  • 针对HRRN算法:

1.使用优先级队列: 使用优先级队列或小根堆数据结构存储未完成的进程,根据动态计算的响应比作为优先级直接挑选下一个调度的进程,将选择最佳进程操作的时间复杂度从 O(n) 降低到 O(log n)。

2.响应比预计算与缓存: 动态更新响应比时,多核处理器可以对未完成进程进行并行计算,进一步提高选择效率。

  • 针对RR算法:

1.动态时间片: 根据当前系统负载或进程历史运行情况动态调整时间片大小(如短任务设置更小的时间片以减少等待时间,长任务设置更大的时间片以减少切换次数),从而提高调度的公平性与实时性。

2.使用多队列调度: 对到达时间相近或服务时间类似的进程分组,分组后对同组的进程使用简单的RR进行调度,组间采用优先级调度,这可以在兼顾公平性的基础上提高调度效率。

3.并发性改进: 通过将多核处理器应用于就绪队列的并行管理,在处理大量进程时,通过同时处理多个进程的调度决策减少队列处理迟滞。

5.3 经验和体会

在实现过程中,理解进程状态转变对调度算法的关键影响,对算法的效率与稳定性有更深刻的认识。

六、用户使用说明

使用程序步骤如下:

  • 编译并运行程序。
  • 按提示输入进程个数 n 及每个进程的到达时间和服务时间。
  • 根据提示输入1选择高响应比优先调度算法或2选择时间片轮转调度算法。
  • 查看输出结果,进程调度状态以及相关统计信息。

七、测试结果

输入:

高响应比优先(HRRN)调度结果:

时间片轮转(RR)调度结果:

Q=2:

Q=4:

总结:

算法

进程名

A

B

C

D

E

平均

到达时间

0

1

2

3

4

服务时间

6

2

5

9

8

HRRN

完成时间

6

8

13

30

21

周转时间

6

7

11

27

17

13.6

带权周转时间

1

3.5

2.2

3

2.125

2.365

RR

q=2

完成时间

16

4

21

30

29

周转时间

16

3

19

27

25

18

带权周转时间

2.67

1.5

3.8

3

3.13

2.81

RR

q=4

完成时间

20

6

21

30

29

周转时间

20

5

19

27

25

19.2

带权周转时间

3.33

2.5

3.8

3

3.13

3.15

#include <bits/stdc++.h>
using namespace std;
struct Process {
    int id;
    int arrivalTime; // 到达时间
    int serviceTime; // 服务时间
    int remainingTime; // 剩余服务时间(RR)
    int finishTime;  // 完成时间
    int wholeTime;   // 周转时间
    double weightedWholeTime; // 带权周转时间
    int flag; //是否进入(RR)
};

// HRRN算法调度函数
void hrrn(vector<Process>& processes, int n) {
    int currentTime = 0;
    int completed = 0;
    vector<bool> finished(n, false); // 标识每个进程是否已完成

    while (completed < n) {
        double bestResponseRatio = -1;
        int bestProcess = -1;

        // 遍历所有进程,选择当前响应比最高的进程
        for (int i = 0; i < n; ++i) {
            if (!finished[i] && processes[i].arrivalTime <= currentTime) {
                double responseRatio = (double)(currentTime - processes[i].arrivalTime + processes[i].serviceTime) / processes[i].serviceTime;
                if (responseRatio > bestResponseRatio) {
                    bestResponseRatio = responseRatio;
                    bestProcess = i;
                }
            }
        }

        if (bestProcess != -1) {// 如果找到合适的进程进行调度
            Process& p = processes[bestProcess];
            currentTime += p.serviceTime;
            p.finishTime = currentTime;
            p.wholeTime = p.finishTime - p.arrivalTime;
            p.weightedWholeTime = (double)p.wholeTime / p.serviceTime;
            finished[bestProcess] = true;
            completed++;
            cout << "时刻" << currentTime << ":进程" << p.id << "完成运行" << endl;
        }
        else {
            currentTime++;
        }
    }
}

void roundRobin(vector<Process>& processes, int n, int q) {
    int currentTime = 0;
    int completed = 0;
    queue<int> readyQueue;
    // 将到达时间为0的进程加入就绪队列
    for (int i = 0; i < n; ++i) {
        if (processes[i].arrivalTime == 0) {
            processes[i].flag = 1;
            readyQueue.push(i);
        }
            
    }

    while (completed < n) {
        if (!readyQueue.empty()) {
            int i = readyQueue.front();
            readyQueue.pop();
            Process& p = processes[i];

            if (p.remainingTime > q) {
                currentTime += q;
                p.remainingTime -= q;
                cout << "时刻" << currentTime << ":进程" << p.id << "运行了" << q << "时间片" << endl;
            }
            else {
                currentTime += p.remainingTime;
                p.remainingTime = 0;
                p.finishTime = currentTime;
                p.wholeTime = p.finishTime - p.arrivalTime;
                p.weightedWholeTime = (double)p.wholeTime / p.serviceTime;
                cout << "时刻" << currentTime << ":进程" << p.id << "完成运行" << endl;
                completed++;
            }
            // 遍历所有进程,将符合条件的进程加入就绪队列(尚未完成的进程)
            for (int j = 0; j < n; ++j) {
                if (processes[j].arrivalTime <= currentTime && j != i && processes[j].remainingTime > 0 && processes[j].flag ==0) {
                    processes[j].flag = 1;
                    readyQueue.push(j);
                }
            }
            // 如果当前进程尚未完成,则重新将其加入到就绪队列
            if (p.remainingTime > 0) {
                readyQueue.push(i);
            }
        }
        else {
            currentTime++;
            for (int j = 0; j < n; ++j) {
                if (processes[j].arrivalTime <= currentTime && processes[j].remainingTime > 0 && processes[j].flag==0) {
                    processes[j].flag = 1;
                    readyQueue.push(j);
                }
            }
        }
    }
}

int main() {
    int n;
    cout << "输入进程数量: ";
    cin >> n;
    if (n > 1e4) {
        cout << "进程数量太多" << endl;
        return 1;
    }
    vector<Process> processes(n);

    for (int i = 0; i < n; ++i) {
        processes[i].id = i + 1;
        cout << "输入进程" << processes[i].id << "的到达时间和服务时间: ";
        cin >> processes[i].arrivalTime >> processes[i].serviceTime;
        if (processes[i].arrivalTime < 0) {
            cout << "到达时间不能低于0!请重新输入" << endl;
            i--;
        }
        else if (processes[i].serviceTime <= 0) {
            cout << "服务时间应为正整数!请重新输入" << endl;
            i--;
        }
        processes[i].remainingTime = processes[i].serviceTime;
        processes[i].flag = 0;
    }

    int algorithmChoice;
    cout << "选择算法(1-高响应比优先调度,2-时间片轮转调度): ";
    cin >> algorithmChoice;

    if (algorithmChoice == 1) {
        cout << "选择高响应比优先调度算法" << endl;
        hrrn(processes, n);
    }
    else if (algorithmChoice == 2) {
        int q;
        cout << "输入时间片大小: ";
        cin >> q;
        cout << "选择时间片轮转调度算法" << endl;
        roundRobin(processes, n, q);
    }
    else {
        cout << "无效的选择" << endl;
        return 1;
    }

    double totalWholeTime = 0, totalWeightedWholeTime = 0;
    for (int i = 0; i < n; ++i) {
        totalWholeTime += processes[i].wholeTime;
        totalWeightedWholeTime += processes[i].weightedWholeTime;
    }
    double averageWholeTime = totalWholeTime / n;
    double averageWeightedWholeTime = totalWeightedWholeTime / n;

    cout << "\n进程调度结果:" << endl;
    for (int i = 0; i < n; ++i) {
        cout << "进程" << processes[i].id
            << ": 完成时间=" << processes[i].finishTime
            << ", 周转时间=" << processes[i].wholeTime
            << ", 带权周转时间=" << processes[i].weightedWholeTime << endl;
    }
    cout << "平均周转时间: " << averageWholeTime << endl;
    cout << "平均带权周转时间: " << averageWeightedWholeTime << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值