实验一 多级反馈队列调度算法
一. 主要实现方法和代码介绍
1.编写进程类,其只包含所需的运行时间和进程编号两个属性,还有一个运行方法,此方法就是将所需的运行时间属性减去.传入的运行时间.
2.创建进程函数:创建maxp个进程,(应该不超过10,在此创建九个,即暂时不进行进程队列越界处理),其运行时间符合均值为0,方差为20的高斯分布,并取整取绝对之后所得到的值, (此处是为了全自动创建进程),进程号自己自增. 在创建进程时,使用mutex库将每一个queue 加锁和解锁,以实现互斥访问.
3.运行函数. 主要的算法函数. 首先判断队列非空,即进入运行,一级队列非空时,优先运行第一级队列,一级队列空后,才检差后几级队列. 但是后几级队列每一次执行后,都重新检查一级队列是否非空.具体实现是:if(一级队列非空) { while(一级队列非空){ 运行}} ;而高级别不执行while. 其次,当一次执行没有执行完,则立即放入下一级队列,每次写入都加锁.
二. 程序流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B8AyJRjO-1647856457764)(C:\Users\51330\AppData\Roaming\Typora\typora-user-images\image-20211009101816266.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S14kJ5Lg-1647856457765)(C:\Users\51330\AppData\Roaming\Typora\typora-user-images\image-20211009101923526.png)]
三. 程序代码
#include <iostream>
#include <queue>
//随机数
#include <random>
#include <chrono>
#include <cmath>
#include <thread>
#include <mutex>#define T 10
#define Qsize 10
using namespace std;
mutex mym1;
mutex mym2;
mutex mym3;
mutex mym4;
int ALLP = 0;
int CPUTIME = 0;
int information = 0;
class Process
{
public:int RUNTIME;int PNUM;void run(int runt);
};
void Process::run(int rt)
{cout << CPUTIME << ":" << ends;if (rt >= RUNTIME){RUNTIME = 0;cout << "进程" << PNUM << "已运行完." << endl;CPUTIME += rt;}else{RUNTIME -= rt;cout << "进程" << PNUM << "已运行" << rt << "时,还需" << RUNTIME << "时即可运行完." << endl;CPUTIME += rt;}
}
queue<Process> q1, q2, q3, q4;
void createProcess(int maxp)
{// 从epoch(1970年1月1日00:00:00 UTC)开始经过的纳秒数,unsigned类型会截断这个值unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();std::default_random_engine generator(seed);// 第一个参数为高斯分布的平均值,第二个参数为标准差std::normal_distribution<double> distribution(0.0, 20.0);// for (int i = 0; i < 10; ++i)// std::cout << distribution(generator) << std::endl;for (int i = 1; i <= maxp; i++){Process c1;c1.RUNTIME = std::abs((int)distribution(generator));c1.PNUM = ALLP++;mym1.lock();q1.push(c1);mym1.unlock();cout << "已创建" << ALLP - 1 << "号进程,需要" << c1.RUNTIME << "时来完成." << endl;}information++;
}
void running()
{int performed = 0;while (true){// if (!q1.empty() || !q2.empty() || !q3.empty() || !q4.empty()){if (!q1.empty()){while (!q1.empty()){Process c1 = q1.front();mym1.lock(); // lockq1.pop();mym1.unlock();c1.run(T);if (c1.RUNTIME != 0){if (q2.size() < Qsize){mym2.lock(); //加锁q2.push(c1);mym2.unlock();}else{暂时没管队列已满时的卡死状态}}}}else if (!q2.empty()){Process c2 = q2.front();mym2.lock();q2.pop();mym2.unlock();c2.run(2 * T);if (c2.RUNTIME != 0){if (q3.size() < Qsize){mym3.lock();q3.push(c2);mym3.unlock();}else{暂时没管队列已满时的卡死状态}}if (!performed){createProcess(9);performed = 1;}}else if (!q3.empty()){Process c3 = q3.front();mym3.lock();q3.pop();mym3.unlock();c3.run(4 * T);if (c3.RUNTIME != 0){if (q4.size() < Qsize){mym4.lock();q4.push(c3);mym4.unlock();}else{暂时没管队列已满时的卡死状态}}}else if (!q4.empty()){Process c4 = q4.front();mym4.lock();q4.pop();mym4.unlock();c4.run(8 * T);if (c4.RUNTIME != 0){if (q4.size() < Qsize){mym4.lock();q4.push(c4);mym4.unlock();}else{暂时没管队列已满时的卡死状态}}}else{cout << CPUTIME << ":当前时刻所有进程已运行完." << endl;while (!q1.empty() || !q2.empty() || !q3.empty() || !q4.empty()){break;}if (information == 2)break;} // }}}
}
int main()
{// thread t1(createProcess, 9);createProcess(9);thread t2(running);// t1.join();t2.join();return 0;
}
四. 运行结果
五.结果分析
观察上方运行结果即可得到:
-
先进行创建进程,创建了九个进程. 而后当一级队列运行完成后,再次创建了九个进程,后面重新从一级队列开始运行. 运行完后,才运行下级队列的1~7号进程.
故可以看出,一级队列最高优先级实现成功.
-
代码缺陷分析:
- 创建进程和运行不能同步进行. 虽然尝试实现创建两个线程,让运行函数和创建进程的函数分开运行,通过对共享变量(共享内存通信)的修改通知不同的进程运行,但总是进入死循环,尝试失败
- 没有按照老师上课讲得PCB的大部分信息来创建进程, 而是偷懒只考虑自己的模拟需求,只有运行时间和进程号两个属性.
. 运行完后,才运行下级队列的1~7号进程.
故可以看出,一级队列最高优先级实现成功.
-
代码缺陷分析:
- 创建进程和运行不能同步进行. 虽然尝试实现创建两个线程,让运行函数和创建进程的函数分开运行,通过对共享变量(共享内存通信)的修改通知不同的进程运行,但总是进入死循环,尝试失败
- 没有按照老师上课讲得PCB的大部分信息来创建进程, 而是偷懒只考虑自己的模拟需求,只有运行时间和进程号两个属性.