调度程序的实现包括几个部分:
1.导入task.txt文件,并将其字符串内容分割并以整数形式保存在结构体PCB的成员中。
2.四个调度算法函数,分别是sjf, psjf, pprio, prio。
sjf:最短作业优先调度(非抢占式)
psjf:最短作业优先调度(抢占式)
pprio:优先级调度(非抢占式)
prio:优先级调度(抢占式)
其中:四个调度算法函数大同小异,主要都利用链表(head,tail)和标志位(running、highest/shortest)来实现功能。running用来标志当前运行的进程是哪一个,highest用来标志当前ready队列中优先级最高的进程/shortest用来标志当前ready队列中剩余运行时间最短的进程。
时间由变量t表示,初始化为0,随着t每次自增1,程序将会进行几个判断:1. 遍历检查所有未开始的进程,看看是否有进程要进入ready队列;2.检查当前最高优先级进程/最短调度进程,并将其标志在highest/shortest;3.判断是否能进行调度(分为抢占和非抢占,抢占模式下仅检测标志位highest/shortest;而非抢占模式下需要检测标志位running和highest/shortest);4.判断当前进程是否运行完,如果运行完则将其状态置为terminal。
如果所有进程状态都为terminal,则跳出t自增的循环,并遍历链表,输出调度顺序。
typedef struct node {
int procID; /* 进程ID */
int releaseTime; /* 到达时间 */
int priority; /* 优先级 */
int cpuTime; /* 运行时间 */
int executedTime; /* 已运行时间 */
int state; /* 进程状态 -1是未开始,0是ready,1是running,2是terminal*/
struct node * next; /* 指向下一个进程指针 */
} PCB;
数据结构PCB,既用于存储从文件中读入的初始进程(procID唯一标识),又用于记录调度中的进程。(依据链表排序,输出procID和executedTime作为结果)
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
typedef struct node {
int procID; /* 进程ID */
int releaseTime; /* 到达时间 */
int priority; /* 优先级 */
int cpuTime; /* 运行时间 */
int executedTime; /* 已运行时间 */
int state; /* 进程状态 -1是未开始,0是ready,1是running,2是terminal*/
struct node * next; /* 指向下一个进程指针 */
} PCB;
PCB pcb[10];
void sjf(int n)//非抢占式最短作业优先调度
{
PCB *head = (PCB*)malloc(sizeof(PCB));
int running = -1;//正在运行的进程
int shortest = -1;//当前最短剩余时间进程
for (int i = 0; i < n; i++)//初始化
{
pcb[i].state = -1;
pcb[i].executedTime = 0;
}
for (int i = 0; i < n; i++)
{
if (pcb[i].releaseTime == 0)//把到达时间为0的进程i置为running状态
{
head->procID = pcb[i].procID;
head->executedTime = 1;
pcb[i].state = 1;
pcb[i].executedTime = 1;
//shortest = i;
running = i;
if (pcb[i].executedTime == pcb[i].cpuTime)
{
pcb[i].state = 2;
running = -1;
}
}
}
PCB *tail = head;
int t = 1;
while (true)
{
int flag = 0;
for (int i = 0; i < n; i++)
{
if (pcb[i].state != 2)
{
flag = 0;
break;
}
flag = 1;
}
if (flag) break;//当所有进程的state都为2时,跳出大循环
for (int i = 0; i < n; i++)//遍历检查所有未开始的进程,看看是否有进程要进入ready队列,同时检查当前最短作业进程
{
if (pcb[i].state == -1)
if (pcb[i].releaseTime == t)
{
pcb[i].state = 0;
}
}
for (int i = 0; i < n; i++)
{
if (pcb[i].state == 0)
{
if (shortest == -1)
shortest = i;
if (pcb[i].cpuTime - pcb[i].executedTime < pcb[shortest].cpuTime - pcb[shortest].executedTime)
shortest = i;
}
}
if (running == -1)//将当前最短作业进程置入running,由于是非抢占调度,加了running的锁
{
running = shortest;
PCB *p = (PCB*)malloc(sizeof(PCB));
p->procID = pcb[running].procID;
p->executedTime = 0;
pcb[running].state = 1;
tail->next = p;
tail = p;
shortest = -1;
}
pcb[running].executedTime++;
tail->executedTime++;
if (pcb[running].executedTime == pcb[running].cpuTime)//判断当前进程是否运行完,如果运行完则移出running
{
pcb[running].state = 2;
running = -1;
}
t++;
}
tail->next = nullptr;
for (PCB *p = head; p != nullptr; p = p->next)
{
cout << p->procID << ":" << p->executedTime << endl;
}
}
void psjf(int n)//抢占式最短作业优先调度
{
PCB *head = (PCB*)malloc(sizeof(PCB));
int running = -1;//正在运行的进程
int shortest = -1;//当前最短剩余运行时间的进程
for (int i = 0; i < n; i++)//初始化
{
pcb[i].state = -1;
pcb[i].executedTime = 0;
}
for (int i = 0; i < n; i++)
{
if (pcb[i].releaseTime == 0)//把到达时间为0的进程i置为running状态
{
head->procID = pcb[i].procID;
head->executedTime = 1;
pcb[i].state = 1;
pcb[i].executedTime = 1;
shortest = i;
running = i;
if (pcb[i].executedTime == pcb[i].cpuTime)
{
pcb[i].state = 2;
shortest = -1;
running = -1;
}
}
}
PCB *tail = head;
int t = 1;
while (true)
{
int flag = 0;
for (int i = 0; i < n; i++)
{
if (pcb[i].state != 2)
{
flag = 0;
break;
}
flag = 1;
}
if (flag) break;//当所有进程的state都为2时,跳出大循环
for (int i = 0; i < n; i++)//遍历检查所有未开始的进程,看看是否有进程要进入ready队列,同时检查当前最短作业进程
{
if (pcb[i].state == -1)
if (pcb[i].releaseTime == t)
{
pcb[i].state = 0;
}
}
for (int i = 0; i < n; i++)
{
if (pcb[i].state == 0)
{
if (shortest == -1)
shortest = i;
if (pcb[i].cpuTime - pcb[i].executedTime < pcb[shortest].cpuTime - pcb[shortest].executedTime)
shortest = i;
}
}
if (1)//将当前最短作业进程置入running,由于是抢占调度,没有关于running的锁
{
if (running == shortest)
goto lable;
pcb[running].state = 0;
running = shortest;
PCB *p = (PCB*)malloc(sizeof(PCB));
p->procID = pcb[running].procID;
p->executedTime = 0;
pcb[running].state = 1;
tail->next = p;
tail = p;
}
lable:
pcb[running].executedTime++;
tail->executedTime++;
if (pcb[running].executedTime == pcb[running].cpuTime)//判断当前进程是否运行完,如果运行完则移出running
{
pcb[running].state = 2;
running = -1;
shortest = -1;
}
t++;
}
tail->next = nullptr;
for (PCB *p = head; p != nullptr; p = p->next)
{
cout << p->procID << ":" << p->executedTime << endl;
}
}
void pprio(int n)//非抢占式优先级调度
{
PCB *head = (PCB*)malloc(sizeof(PCB));
int running = -1;//正在运行的进程
int highest = -1;//当前最高优先级进程
for (int i = 0; i < n; i++)//初始化
{
pcb[i].state = -1;
pcb[i].executedTime = 0;
}
for (int i = 0; i < n; i++)
{
if (pcb[i].releaseTime == 0)//把到达时间为0的进程i置为running状态
{
head->procID = pcb[i].procID;
head->executedTime = 1;
pcb[i].state = 1;
pcb[i].executedTime = 1;
running = i;
if (pcb[i].executedTime == pcb[i].cpuTime)
{
pcb[i].state = 2;
running = -1;
}
}
}
PCB *tail = head;
int t = 1;
while (true)
{
int flag = 0;
for (int i = 0; i < n; i++)
{
if (pcb[i].state != 2)
{
flag = 0;
break;
}
flag = 1;
}
if (flag) break;//当所有进程的state都为2时,跳出大循环
for (int i = 0; i < n; i++)//遍历检查所有未开始的进程,看看是否有进程要进入ready队列,同时检查当前最高优先级进程
{
if (pcb[i].state == -1)
if (pcb[i].releaseTime == t)
{
pcb[i].state = 0;
}
}
for (int i = 0; i < n; i++)
{
if (pcb[i].state == 0)
{
if (highest == -1)
highest = i;
if (pcb[i].priority > pcb[highest].priority)
highest = i;
}
}
if (running == -1)//将当前最高优先级的进程置入running,由于是非抢占调度,加了running的锁
{
running = highest;
PCB *p = (PCB*)malloc(sizeof(PCB));
p->procID = pcb[running].procID;
p->executedTime = 0;
pcb[running].state = 1;
tail->next = p;
tail = p;
highest = -1;
}
pcb[running].executedTime++;
tail->executedTime++;
if (pcb[running].executedTime == pcb[running].cpuTime)//判断当前进程是否运行完,如果运行完则移出running
{
pcb[running].state = 2;
running = -1;
}
t++;
}
tail->next = nullptr;
for (PCB *p = head; p != nullptr; p = p->next)
{
cout << p->procID << ":" << p->executedTime << endl;
}
}
void prio(int n)//抢占式优先级调度
{
PCB *head = (PCB*)malloc(sizeof(PCB));
int running = -1;//正在运行的进程
int highest = -1;//当前最高优先级进程
for (int i = 0; i < n; i++)//初始化
{
pcb[i].state = -1;
pcb[i].executedTime = 0;
}
for (int i = 0; i < n; i++)
{
if (pcb[i].releaseTime == 0)//把到达时间为0的进程i置为running状态
{
head->procID = pcb[i].procID;
head->executedTime = 1;
pcb[i].state = 1;
pcb[i].executedTime = 1;
highest = i;
running = i;
if (pcb[i].executedTime == pcb[i].cpuTime)
{
pcb[i].state = 2;
highest = -1;
running = -1;
}
}
}
PCB *tail = head;
int t = 1;
while (true)
{
int flag = 0;
for (int i = 0; i < n; i++)
{
if (pcb[i].state != 2)
{
flag = 0;
break;
}
flag = 1;
}
if (flag) break;//当所有进程的state都为2时,跳出大循环
for (int i = 0; i < n; i++)//遍历检查所有未开始的进程,看看是否有进程要进入ready队列,同时检查当前最高优先级进程
{
if (pcb[i].state == -1)
if (pcb[i].releaseTime == t)
{
pcb[i].state = 0;
}
}
for (int i = 0; i < n; i++)
{
if (pcb[i].state == 0)
{
if (highest == -1)
highest = i;
if (pcb[i].priority > pcb[highest].priority)
highest = i;
}
}
if (1)//将当前最高优先级的进程置入running,由于是抢占调度,没有关于running的锁
{
if (running == highest)
goto lable2;
pcb[running].state = 0;
running = highest;
PCB *p = (PCB*)malloc(sizeof(PCB));
p->procID = pcb[running].procID;
p->executedTime = 0;
pcb[running].state = 1;
tail->next = p;
tail = p;
}
lable2:
pcb[running].executedTime++;
tail->executedTime++;
if (pcb[running].executedTime == pcb[running].cpuTime)//判断当前进程是否运行完,如果运行完则移出running
{
pcb[running].state = 2;
running = -1;
highest = -1;
}
t++;
}
tail->next = nullptr;
for (PCB *p = head; p != nullptr; p = p->next)
{
cout << p->procID <<":"<< p->executedTime << endl;
}
}
int main ()
{
// PCB *p;
// p_head = (PCB*)malloc(sizeof(PCB));
// p = p_head;
char str[20];
char *s;
int n = 0;
ifstream in("task.txt");
string line;
if (in) // 有该文件
{
while (getline(in, line)) // line中不包括每行的换行符
{
if (n == 10)
{
cout << "进程数量溢出(大于10)" << endl;
return -1;
}
int i;
strcpy(str, line.c_str());
s = strtok(str, " ");
i = atoi(s);
pcb[n].procID = i;//进程id
s = strtok(NULL, " ");
i = atoi(s);//到达时间
pcb[n].releaseTime = i;
s = strtok(NULL, " ");
i = atoi(s);
pcb[n].priority = i;//优先级
s = strtok(NULL, " ");
i = atoi(s);
pcb[n].cpuTime = i;//运行时间
n++;
}
}
else // 没有该文件
{
cout << "no such file" << endl;
}
string alt[4]{ "sjf","psjf","pprio","prio" };
cout << "选择调度算法sjf, psjf, pprio, prio" << endl;
string select;
cin >> select;
if (select == alt[0])
sjf(n);
if (select == alt[1])
psjf(n);
if (select == alt[2])
pprio(n);
if (select == alt[3])
prio(n);
return 0;
}
对于文件task.txt ,进行非抢占式和抢占式最短作业优先调度:
sjf:
符合规律:
psjf:
符合规律: