引言
最近学习了操作系统内诸多进程调度算法,动手实现了抢占式优先级调度算法
知识点
该算法又称为优先权调度算法,他既可以用于作业调度,又可用于进程调度。该算法中的优先级用于描述作业运行的紧迫程度。
两种类型:
- 非剥夺式(非抢占式)优先级调度算法。当一个进程正在处理上运行时,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在进行的进程继续运行,直到由于其自身原因而主动让出处理机(任务完成或等待事件),才把处理机分配给更为重要或紧迫的进程。
- 剥夺式(抢占式)优先级调度算法。当一个进程正在处理机上运行时,若有某个更为重要或紧迫的进程进入就绪队列,则立即暂停正在运行的进程,将处理机分配给更重要或紧迫的进程。
两种优先级:
- 静态优先级。优先级是在创建进程时确定的,且在进程的整个运行期间保持不变。确定静态优先级的主要依据有进程类型、进程对资源的要求、用户要求。
- 动态优先级。在进程运行过程中,根据进程情况的变化动态调整优先级。动态调整优先级的主要依据有进程占有 CPU 时间的长短、就绪进程等待 CPU 时间的长短。
一般来说,进程优先级的设置有下面几点原则:
- 系统进程 > 用户进程。系统进程作为系统的管理者,理应拥有更高的优先权。
- 交互型进程 > 非交互型进程。与用户进行交互的进程需要被优先处理,即要有更高的优先级。
- I/O型进程 > 计算型进程。频繁使用 I/O 设备的进程称为 I/O 型进程,I/O 设备的处理速度要比 CPU慢很多,所以将 I/O 型进程的优先级设置得更高,就有可能让 I/O 设备尽早开始工作,进而提升系统的整体效率。
代码实现(C++)
本程序使用两个栈,分别储存运行进程和进程优先级。
使用栈是为了解决一个进程被另一个进程抢占后的恢复问题,之所以 不用一个栈来存储,是为了避免配有相同优先级但不同进程相遇的情况。
#include<iostream>
#include<string>
#include<windows.h>
#include<stack> // 用来存储优先权
#include<list> // 使用list存储PCB,考虑到无法模拟事件的顺序发生,故不使用队列
#define MAXNUM 1000
using namespace std;
typedef struct pcb {
int pID; // 进程编号
int level; // 进程优先权
float needTime; // 需要运行时间
float reachTime; // 到达时间
float leftTime; // 剩余运行时间
}PCB;
void createProcess(int n, list<PCB> &plist) { // 创建一个进程队列
cout<<"请输入相应进程的进程编号、优先权、到达时间、运行时间(类似:1 1 0 4)"<<endl;
for(int i=0;i<n;i++) {
PCB p;
cout<<"请输入第"<<i+1<<"个进程的信息:";
cin>>p.pID>>p.level>>p.reachTime>>p.needTime;
plist.push_front(p);
}
}
int getWholeTime(list<PCB> &plist) { // 获取所有任务的总时间
list<PCB>::iterator i;
int sumTime = 0;
for(i=plist.begin();i!=plist.end();i++) {
sumTime += i->needTime;
}
return sumTime;
}
void runProcess(int n, list<PCB> &plist) { // 运行进程
int Clocker = 0; // 定义一个计时器
stack<int> id_stack; // 定义一个存放进程ID的栈
stack<int> level_stack; // 定义一个存放优先权的栈
level_stack.push(0);
id_stack.push(0);
int sumTime = getWholeTime(plist); // 获取总共运行时间
cout<<endl;
while(Clocker<sumTime) {
cout<<"时间片轮转一个单位..."<<endl;
// 遍历找出当前时刻优先权最高的进程
list<PCB>::iterator i;
for(i = plist.begin();i != plist.end();i++) {
if(i->reachTime<=Clocker && i->level>=level_stack.top() && i->needTime>0) {
if(i->pID != id_stack.top()) {
id_stack.push(i->pID);
level_stack.push(i->level);
}
i->needTime--; // 剩余运行时间减少1个单位
if(i->needTime == 0) { // 若运行结束,对应优先权出栈
level_stack.pop();
id_stack.pop();
}
cout<<"本次执行了进程: "<<i->pID<<endl;
cout<<endl;
break;
}
}
Sleep(1500);
Clocker++;
}
}
/*
测试用例:
pID level reachTime needTime
1 2 0 3
2 4 2 1
3 1 4 3
4 3 6 2
*/
int main() {
cout<<"请输入进程数量:";
int n;
cin>>n;
if(n>MAXNUM) { //过热保护
cout<<"CPU 即将爆炸,倒计时..."<<endl;
Sleep(1000);
cout<<"3..."<<endl;
Sleep(1000);
cout<<"2..."<<endl;
Sleep(1000);
cout<<"1..."<<endl;
Sleep(1000);
cout<<"喵~"<<endl;
return 0;
}
list<PCB> plist;
createProcess(n,plist);
runProcess(n,plist);
cout<<"结束!"<<endl;
return 0;
}