实验内容:
第一部分:作业调度
作业名 |
要求运行时间 |
优先级 |
到达时间 |
链接指针 |
JCB
提示:
(1)假设系统有五个作业,每一个作业投入内存后,操作系统仅为其建立一个进程.
作业名 ----作业标识
要求运行时间----即估计的作业运行时间
优先级 ----为之创建进程的基本优先级
到达时间 ----作业提交的时刻,可用相对时间片时间表示
/*以上三项可随机产生(+1)或用户指定*/
链接指针 ----指向比本作业晚到来或同时到来而运行时间较短的作业
(2)创建作业后应形成按主关键字为到达时间, 次关键字为要求运行时间的作业后备队列.
(3)设置系统计时域,记录运行过的时间片个数,当它的值与作业后备队列队首的一个或多个作业的到达时间一致时,将它(们)投入就绪队列.
(4)应有显示或打印语句,能显示或打印每经过一个系统时间后,就绪队列及作业后备队列的状态.
第二部分:进程调度
(一)优先级调度:
进程名 |
链接指针 |
要求运行时间 |
优先级 |
进程状态 |
PCB
提示:
(1)
优先级 ----作业投入就绪队列,为其创建进程时将作业的基本优先级写入,调度时总是选择优先级最高的进程运行
进程名 ----为作业创建进程时起的名称
链接指针 ----指向就绪队列的下一个进程,就绪队列以优先级为基础排序
要求运行时间----进程运行的相对时间片时间,由为之创建进程的作业处得到
进程状态 ----为简单起见,假定进程仅有就绪和完成状态.进程创建时处于就绪态’R’,运行结束后,置为完成状态’C’,并从就绪队列中删除.
(2)为调度方便,设置一个指针指向就绪队列的第一个进程.
(3)处理机调度时,选择队首进程运行……将队首进程摘除后,运行一个时间片,即执行优先级减一、时间片减一的工作. 若此时要求运行时间为0:此进程运行完毕,状态置为’C’;若不为0,则比较其优先级与队首进程的优先级:当大于等于队首进程的优先级时,继续执行一个时间片,直至小于队首进程的优先级为止,将其插入到就绪队列的合适位置上,再调度队首进程投入运行.
(4)所设计的程序应有显示或打印语句,显示或打印选中进程的进程名及运行一次后进程就绪队列及后备作业队列的状态.
(二)时间片轮转法:(+2)
进程名 |
链接指针 |
要求运行时间 |
进程状态 |
PCB
提示:
(1)链接指针----指向下一个到来进程的PCB首地址,最后一个进程指出第一个进程的PCB首地址.
其它如上题
(2)设置一个队首指针指向就绪循环队列的队首进程.若有新的进程到来,则将其插入到就绪循环队列的尾端,等待下次调度.
(3)执行处理机调度时,总是选择队首进程运行.仅执行要求运行时间减一的工作.
(4)进程运行一次后,判断运行时间是否为0:若为0,则置状态为’C’,并推出循环就绪队列;若不为0,将其置于循环队列的尾端,等待下一轮的运行.
(5)若就绪队列不空,反复执行(3)、(4)步骤,直至所有进程都运行完为止.
(6)所设计的调度程序中,应包含显示或打印语句,以便显示或打印每次选中的进程名及运行一次后进程就绪队列和作业后备队列的变化情况.
实现:
我并没有完全按照实验内容来做。
实现的算法是短进程优先以及时间片轮转,进程由作业生成。
程序流程如下:
1、首先随机生成多个作业,对生成的作业按到达时间排序。
2、时间片轮转开始。
3、检查就绪队列、后备队列、作业调度表是否都为空。如果是,跳到7,程序结束,否则继续执行。
4、检查是否有作业到达。若有作业到达,将作业投入后备队列,并按短进程优先排序,同时检查就绪队列是否已满。如果没有作业到达,则进行下一步。
5、如果就绪队列不满,且后备队列不为空,则将后备队列队首转换为进程投入就绪队列队尾;后备队列为空,则不做处理。如果就绪队列已满,则进行下一步。
6、提取就绪队列队首进程放入运行队列,将其运行时间-1,然后检查运行时间是否为0。若运行时间为0,将进程投入已完成队列队尾;若运行时间不为0,将进程投入回就绪队列队尾。
7、程序结束。
程序中有5种队列,作业调度表,后备队列,就绪队列,运行队列,已完成队列。
作业调度表:存放生成的作业,按到达时间从小到大排序。
后备队列:存放虽然已到达,但还没有参与处理机资源分配的作业。
就绪队列:存放已到达,且已参与处理机资源分配的作业。轮转分配资源。
运行队列:存放当前正在运行的队列。同一时间,该队列最多有一个进程(单处理机)
已完成队列:存放运行时间为0,即已完成的作业。
实验结果:
此为运行结果的一部分,完整版可以见下(由于是随机生成作业,所以完整版和截图并不相同):
--- 作业调度表 --- 作业名 到达时间 工作时间 Job6 2 1 Job2 2 8 Job9 3 6 Job7 5 3 Job4 6 2 Job3 6 2 Job1 7 1 Job5 8 2 Job8 9 1 # 开始时间片轮转 ------------------------------------------------------ 当前系统时间 : 1 # 无作业到达 # 就绪队列: => 空 # 已完成进程队列: => 空 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 2 # 将作业Job6投入到后备队列 # 将作业Job2投入到后备队列 # 将作业Job6投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process6 1 W --- 后备队列 --- 作业名 到达时间 工作时间 Job2 2 8 --- 作业调度表 --- 作业名 到达时间 工作时间 Job9 3 6 Job7 5 3 Job4 6 2 Job3 6 2 Job1 7 1 Job5 8 2 Job8 9 1 # 进程Process6已完成,退出就绪队列 # 就绪队列: => 空 # 已完成进程队列: => Process6 # 后备队列: => Job2 ------------------------------------------------------ 当前系统时间 : 3 # 将作业Job9投入到后备队列 # 将作业Job9投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process9 6 W --- 后备队列 --- 作业名 到达时间 工作时间 Job2 2 8 --- 作业调度表 --- 作业名 到达时间 工作时间 Job7 5 3 Job4 6 2 Job3 6 2 Job1 7 1 Job5 8 2 Job8 9 1 # 就绪队列: => Process9 # 已完成进程队列: => Process6 # 后备队列: => Job2 ------------------------------------------------------ 当前系统时间 : 4 # 无作业到达 # 将作业Job2投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process9 5 W Process2 8 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 Job7 5 3 Job4 6 2 Job3 6 2 Job1 7 1 Job5 8 2 Job8 9 1 # 就绪队列: => Process2->Process9 # 已完成进程队列: => Process6 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 5 # 将作业Job7投入到后备队列 # 将作业Job7投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 8 W Process9 4 R Process7 3 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 Job4 6 2 Job3 6 2 Job1 7 1 Job5 8 2 Job8 9 1 # 就绪队列: => Process9->Process7->Process2 # 已完成进程队列: => Process6 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 6 # 将作业Job4投入到后备队列 # 将作业Job3投入到后备队列 # 将作业Job3投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process9 4 W Process7 3 R Process2 7 R Process3 2 R --- 后备队列 --- 作业名 到达时间 工作时间 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 Job1 7 1 Job5 8 2 Job8 9 1 # 就绪队列: => Process7->Process2->Process3->Process9 # 已完成进程队列: => Process6 # 后备队列: => Job4 ------------------------------------------------------ 当前系统时间 : 7 # 将作业Job1投入到后备队列 # 将作业Job1投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process7 3 W Process2 7 R Process3 2 R Process9 3 R Process1 1 R --- 后备队列 --- 作业名 到达时间 工作时间 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 Job5 8 2 Job8 9 1 # 就绪队列: => Process2->Process3->Process9->Process1->Process7 # 已完成进程队列: => Process6 # 后备队列: => Job4 ------------------------------------------------------ 当前系统时间 : 8 # 将作业Job5投入到后备队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 7 W Process3 2 R Process9 3 R Process1 1 R Process7 2 R --- 后备队列 --- 作业名 到达时间 工作时间 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 Job8 9 1 # 就绪队列: => Process3->Process9->Process1->Process7->Process2 # 已完成进程队列: => Process6 # 后备队列: => Job5->Job4 ------------------------------------------------------ 当前系统时间 : 9 # 将作业Job8投入到后备队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process3 2 W Process9 3 R Process1 1 R Process7 2 R Process2 6 R --- 后备队列 --- 作业名 到达时间 工作时间 Job8 9 1 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process9->Process1->Process7->Process2->Process3 # 已完成进程队列: => Process6 # 后备队列: => Job8->Job5->Job4 ------------------------------------------------------ 当前系统时间 : 10 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process9 3 W Process1 1 R Process7 2 R Process2 6 R Process3 1 R --- 后备队列 --- 作业名 到达时间 工作时间 Job8 9 1 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process1->Process7->Process2->Process3->Process9 # 已完成进程队列: => Process6 # 后备队列: => Job8->Job5->Job4 ------------------------------------------------------ 当前系统时间 : 11 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process1 1 W Process7 2 R Process2 6 R Process3 1 R Process9 2 R --- 后备队列 --- 作业名 到达时间 工作时间 Job8 9 1 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process1已完成,退出就绪队列 # 就绪队列: => Process7->Process2->Process3->Process9 # 已完成进程队列: => Process6->Process1 # 后备队列: => Job8->Job5->Job4 ------------------------------------------------------ 当前系统时间 : 12 # 无作业到达 # 将作业Job8投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process7 2 W Process2 6 R Process3 1 R Process9 2 R Process8 1 R --- 后备队列 --- 作业名 到达时间 工作时间 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process2->Process3->Process9->Process8->Process7 # 已完成进程队列: => Process6->Process1 # 后备队列: => Job5->Job4 ------------------------------------------------------ 当前系统时间 : 13 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 6 W Process3 1 R Process9 2 R Process8 1 R Process7 1 R --- 后备队列 --- 作业名 到达时间 工作时间 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process3->Process9->Process8->Process7->Process2 # 已完成进程队列: => Process6->Process1 # 后备队列: => Job5->Job4 ------------------------------------------------------ 当前系统时间 : 14 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process3 1 W Process9 2 R Process8 1 R Process7 1 R Process2 5 R --- 后备队列 --- 作业名 到达时间 工作时间 Job5 8 2 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process3已完成,退出就绪队列 # 就绪队列: => Process9->Process8->Process7->Process2 # 已完成进程队列: => Process6->Process1->Process3 # 后备队列: => Job5->Job4 ------------------------------------------------------ 当前系统时间 : 15 # 无作业到达 # 将作业Job5投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process9 2 W Process8 1 R Process7 1 R Process2 5 R Process5 2 R --- 后备队列 --- 作业名 到达时间 工作时间 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process8->Process7->Process2->Process5->Process9 # 已完成进程队列: => Process6->Process1->Process3 # 后备队列: => Job4 ------------------------------------------------------ 当前系统时间 : 16 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process8 1 W Process7 1 R Process2 5 R Process5 2 R Process9 1 R --- 后备队列 --- 作业名 到达时间 工作时间 Job4 6 2 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process8已完成,退出就绪队列 # 就绪队列: => Process7->Process2->Process5->Process9 # 已完成进程队列: => Process6->Process1->Process3->Process8 # 后备队列: => Job4 ------------------------------------------------------ 当前系统时间 : 17 # 无作业到达 # 将作业Job4投入到就绪队列 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process7 1 W Process2 5 R Process5 2 R Process9 1 R Process4 2 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process7已完成,退出就绪队列 # 就绪队列: => Process2->Process5->Process9->Process4 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 18 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 5 W Process5 2 R Process9 1 R Process4 2 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process5->Process9->Process4->Process2 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 19 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process5 2 W Process9 1 R Process4 2 R Process2 4 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process9->Process4->Process2->Process5 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 20 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process9 1 W Process4 2 R Process2 4 R Process5 1 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process9已完成,退出就绪队列 # 就绪队列: => Process4->Process2->Process5 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 21 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process4 2 W Process2 4 R Process5 1 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process2->Process5->Process4 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 22 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 4 W Process5 1 R Process4 1 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process5->Process4->Process2 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 23 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process5 1 W Process4 1 R Process2 3 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process5已完成,退出就绪队列 # 就绪队列: => Process4->Process2 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9->Process5 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 24 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process4 1 W Process2 3 R --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process4已完成,退出就绪队列 # 就绪队列: => Process2 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9->Process5->Process4 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 25 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 3 W --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process2 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9->Process5->Process4 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 26 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 2 W --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => Process2 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9->Process5->Process4 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 27 # 无作业到达 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 Process2 1 W --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 进程Process2已完成,退出就绪队列 # 就绪队列: => 空 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9->Process5->Process4->Process2 # 后备队列: => 空 ------------------------------------------------------ 当前系统时间 : 28 --- 运行队列 & 就绪队列 & 已完成队列 --- 进程名 运行时间 进程状态 --- 后备队列 --- 作业名 到达时间 工作时间 --- 作业调度表 --- 作业名 到达时间 工作时间 # 就绪队列: => 空 # 已完成进程队列: => Process6->Process1->Process3->Process8->Process7->Process9->Process5->Process4->Process2 # 后备队列: => 空 ------------------------------------------------------
源代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <time.h> 4 #include <stdlib.h> 5 #include <string.h> 6 using namespace std; 7 8 #define JOBSUM 9 //进程/作业总数 9 #define JOBNUM 5 //允许的作业道数 10 #define PRITOP 3 //最高优先级级数 11 #define TIMELIMIT 10 //时间限制 12 13 struct Job{ //作业 14 char jname[40]; //作业名 15 int start; //到达时间 16 int pri; //优先级 17 int worktime; //工作时间 18 Job *next; //链接指针 19 }; 20 21 struct PCB{ 22 PCB* next; 23 char pname[40]; //进程名 24 int time; //进程运行时间 25 char status; //运行状态 26 }; 27 28 bool CreateJob(Job* jobtable,char name[]) //创建作业,将作业放入作业调度表 29 { 30 //随机生成一个作业 31 Job *p = new Job; 32 strcpy(p->jname,name); 33 p->start = rand()%(TIMELIMIT-1)+1; 34 p->worktime = rand()%(TIMELIMIT-p->start)+1; 35 p->pri = rand()%PRITOP; 36 p->next = NULL; 37 38 //将作业放入作业调度表 39 Job* now = jobtable; 40 41 //将作业放入作业调度表,按到达时间排序 42 if(now->next==NULL){ //后备队列还是空的时候 43 now->next = p; 44 } 45 else{ 46 if(p->start <= now->next->start){ //当新生成的作业工作时间比后备队列第一个作业工作时间就小 47 p->next = now->next; 48 now->next = p; 49 } 50 else{ 51 Job *q = now->next; 52 while( (p->start > q->start) && (q->next!=NULL) ){ //找到插入的位置 53 q = q->next; 54 } 55 if( (p->start > q->start) && q->next==NULL){ //新生成的作业的start比后备队列中所有作业的start都大,则排在最后 56 q->next = p; 57 } 58 else if(p->start <= q->start){ //找到插入的位置,这个位置的start小于或者等于下一个节点的start 59 Job *t = now->next; 60 while(t->next!=q){ 61 t = t->next; 62 } 63 t->next = p; 64 p->next = q; 65 } 66 } 67 } 68 69 return true; 70 } 71 72 bool AddHoubei(Job *jobtable,Job *p,Job *&jhead) //将作业p放入后备队列jhead,按短作业优先放置 73 { 74 //将作业p从作业调度表jobtable中去除 75 Job* q = jobtable; 76 while(q->next!=p && q->next!=NULL){ 77 q = q->next; 78 } 79 if(q->next==p){ 80 q->next = p->next; 81 p->next = NULL; 82 } 83 84 //将作业p放入后备队列jhead,按短作业优先放置 85 if(jhead==NULL){ //后备队列还是空的时候 86 jhead = p; 87 } 88 else{ 89 if(p->worktime <= jhead->worktime){ //当新生成的作业工作时间比后备队列第一个作业工作时间就小 90 p->next = jhead; 91 jhead = p; 92 } 93 else{ 94 Job *q = jhead; 95 while( (p->worktime > q->worktime) && (q->next!=NULL) ){ //找到插入的位置 96 q = q->next; 97 } 98 if( (p->worktime > q->worktime) && q->next==NULL){ //新生成的作业的worktime比后备队列中所有作业的worktime都大,则排在最后 99 q->next = p; 100 } 101 else if(p->worktime <= q->worktime){ //找到插入的位置,这个位置的worktime小于或者等于下一个节点的worktime 102 Job *t = jhead; 103 while(t->next!=q){ 104 t = t->next; 105 } 106 t->next = p; 107 p->next = q; 108 } 109 } 110 } 111 return true; 112 113 } 114 115 bool CreateProcess(PCB* &head,PCB* &tail,Job* &jhead) //创建新进程 116 { 117 PCB* p = new PCB; 118 char JobID = jhead->jname[3]; 119 strcpy(p->pname,"Process"); //进程名 120 p->pname[7] = JobID; 121 p->pname[8] = ‘\0‘; 122 p->status = ‘R‘; //就绪状态 123 p->time = jhead->worktime; //进程工作时间 124 125 if(tail==NULL){ 126 //就绪队列还是空的,则第一次赋值 127 head = p; 128 tail = head; 129 tail->next = head; 130 } 131 else{ 132 //就绪队列不为空 133 tail->next = p; 134 tail = p; 135 p->next = head; 136 } 137 138 return true; 139 } 140 141 bool Work(PCB* now) //当前进程执行 142 { 143 now->time--; 144 145 return true; 146 } 147 148 bool DropPro(PCB* &head,PCB* &tail,PCB* &chead,PCB* &ctail) //将队首进程,推出循环就绪队列 149 { 150 PCB* p = head; //保存头节点 151 head = head->next; //头结点指向他的下一个节点 152 tail->next = head; //将就绪队列尾节点直接指向新的头节点 153 p->next = NULL; //将分离出来的原来的头节点的next设为空NULL 154 155 if(ctail==NULL){ 156 //已完成进程队列还是空的,则第一次赋值 157 chead = p; 158 ctail = chead; 159 } 160 else{ 161 //已完成进程队列不为空,则将当前已完成进程放到队列尾部 162 ctail->next = p; 163 ctail = ctail->next; 164 } 165 166 return true; 167 } 168 169 bool NextPro(PCB* &head,PCB* &tail) //当前进程已执行了一个时间片,将其置于循环队列尾端。即将head和tail向前推进一次 170 { 171 head = head->next; 172 tail = tail->next; 173 174 return true; 175 } 176 177 178 void printRQ(PCB* head,int readynum) //打印当前就绪队列 179 { 180 PCB* p = head; 181 printf("=> "); 182 if(readynum==0){ 183 //就绪队列已空 184 printf("空\n"); 185 return ; 186 } 187 while(p->next!=head){ 188 printf("%s->",p->pname); 189 p = p->next; 190 } 191 printf("%s\n",p->pname); 192 } 193 194 void printCQ(PCB* chead,PCB* ctail) //打印当前已完成进程队列 195 { 196 PCB* p = chead; 197 printf("=> "); 198 if(chead==NULL){ 199 //已完成进程队列队列已空 200 printf("空\n"); 201 return ; 202 } 203 while(p!=ctail){ 204 printf("%s->",p->pname); 205 p = p->next; 206 } 207 printf("%s\n",p->pname); 208 } 209 210 void printJQ(Job* jhead) //打印当前后备队列 211 { 212 Job* p = jhead; 213 printf("=> "); 214 if(jhead==NULL){ 215 printf("空\n"); 216 return ; 217 } 218 while(p->next!=NULL){ 219 printf("%s->",p->jname); 220 p = p->next; 221 } 222 printf("%s\n",p->jname); 223 } 224 225 void getJobName(int i,char name[]) //获得当前进程名 226 { 227 //进程名 228 strcpy(name,"Job"); 229 int len = strlen(name); 230 name[len] = ‘0‘+i; 231 name[len+1] = ‘\0‘; 232 } 233 234 235 void printProInfo(PCB* now) //打印当前进程信息 236 { 237 if(now==NULL){ 238 printf("当前没有进程\n"); 239 return ; 240 } 241 printf("# 当前进程为\n"); 242 printf("进程名:%s\n",now->pname); 243 printf("运行时间:%d\n",now->time); 244 printf("进程状态:%c\n",now->status); 245 } 246 247 void printAllJobInfo(Job* jhead) //输出所有作业信息 248 { 249 Job* p = jhead->next; 250 printf("\t--- 作业调度表 ---\n"); 251 printf("作业名\t"); 252 printf("到达时间\t"); 253 printf("工作时间\n"); 254 while(p!=NULL){ 255 printf("%s\t",p->jname); 256 printf("%d\t\t",p->start); 257 printf("%d\n",p->worktime); 258 p = p->next; 259 } 260 } 261 262 263 void printQueueInfo(Job *jobtable,Job *jhead,PCB *head,PCB *rhead,PCB *chead,int tablenum,int houbeinum,int readynum) //打印所有队列信息 264 { 265 printf("\n"); 266 printf("--- 运行队列 & 就绪队列 & 已完成队列 ---\n"); 267 printf("进程名\t\t"); 268 printf("运行时间\t"); 269 printf("进程状态\t"); 270 printf("\n"); 271 272 PCB *p = NULL; 273 //输出运行队列信息 274 if(readynum!=0){ 275 p = rhead; 276 printf("%s\t",p->pname); 277 printf("%d\t\t",p->time); 278 printf("%c\t",‘W‘); 279 printf("\n"); 280 } 281 282 //输出就绪队列信息 283 if(readynum!=0){ 284 p = head->next; 285 while(p!=head){ 286 printf("%s\t",p->pname); 287 printf("%d\t\t",p->time); 288 printf("%c\t",p->status); 289 printf("\n"); 290 p = p->next; 291 } 292 } 293 294 //输出完成队列 295 if(chead!=NULL){ //完成队列不为空 296 p = chead; 297 while(p!=chead){ 298 printf("%s\t",p->pname); 299 printf("%d\t\t",p->time); 300 printf("%c\t",p->status); 301 printf("\n"); 302 p = p->next; 303 } 304 } 305 306 307 printf("\n"); 308 printf("\t--- 后备队列 ---\n"); 309 printf("作业名\t"); 310 printf("到达时间\t"); 311 printf("工作时间\t"); 312 printf("\n"); 313 314 Job *q; 315 //输出后备队列 316 if(houbeinum!=0){ 317 q = jhead; 318 while(q!=NULL){ 319 printf("%s\t",q->jname); 320 printf("%d\t\t",q->start); 321 printf("%d\t",q->worktime); 322 printf("\n"); 323 q = q->next; 324 } 325 } 326 327 printf("\n"); 328 printf("\t--- 作业调度表 ---\n"); 329 printf("作业名\t"); 330 printf("到达时间\t"); 331 printf("工作时间\t"); 332 printf("\n"); 333 334 //输出作业调度表 335 if(tablenum!=0){ 336 q = jobtable->next; 337 while(q!=NULL){ 338 printf("%s\t",q->jname); 339 printf("%d\t\t",q->start); 340 printf("%d\t",q->worktime); 341 printf("\n"); 342 q = q->next; 343 } 344 } 345 printf("\n"); 346 } 347 348 349 void printQueueInfo2(PCB *head,PCB *chead,PCB *ctail,Job *jhead,int readynum) //打印所有队列信息,第二形态,队列式 350 { 351 printf("\n"); 352 printf("# 就绪队列:\n"); 353 printRQ(head,readynum); 354 355 printf("# 已完成进程队列:\n"); 356 printCQ(chead,ctail); 357 358 printf("# 后备队列:\n"); 359 printJQ(jhead); 360 361 printf("------------------------------------------------------\n"); 362 } 363 364 int main() 365 { 366 PCB *head=NULL,*tail=NULL; //就绪队列 367 PCB *rhead=NULL; //运行队列(运行队列中节点数始终<=1) 368 PCB *chead=NULL,*ctail=NULL; //已完成进程队列 369 Job *jhead=NULL; //后备队列 370 Job *jobtable = new Job; //作业调度表 371 jobtable->next = NULL; 372 int i; 373 int tablenum=0; //作业调度表中作业数量 374 int houbeinum=0; //后备队列的作业数量 375 int readynum=0; //就绪队列进程数 376 377 //将结果输出到日志文件 378 //freopen("ProcessScheduingLog.log","w",stdout); 379 380 //初始化 381 srand((unsigned)time(0)); //设置种子 382 383 for(i=1;i<=JOBSUM;i++){ //初始化每一个进程 384 char name[40]; 385 getJobName(i,name); //获得作业名 386 387 if(!CreateJob(jobtable,name)){ //随机创建一个新作业,放入作业调度表中,作业调度表中作业是无序的。 388 printf("Error 1!\n"); //出现错误,直接退出 389 return 0; 390 } 391 else{ //创建成功 392 tablenum++; 393 } 394 } 395 396 //输出所有作业信息 397 printAllJobInfo(jobtable); 398 399 printf("\n"); 400 printf("# 开始时间片轮转\n"); 401 printf("\n"); 402 printf("------------------------------------------------------\n"); 403 404 int curtime = 0; //系统计时域,运行过的时间片个数 405 //时间片轮转进程调度 406 while(readynum!=0 || houbeinum!=0 || tablenum!=0){ //直到就绪队列为空 且 后备队列为空 且 作业调度表为空,退出循环 407 408 curtime++; //计时+1 409 printf("当前系统时间 : %d\n",curtime); 410 printf("\n"); 411 412 //先检查作业调度表,有到达作业,放入后备队列 413 bool isArrive = false; 414 Job* p = jobtable->next; 415 while(p!=NULL){ 416 if(p->start==curtime){ //有作业到达,将作业放入后备队列,并按短作业优先放置 417 isArrive = true; 418 Job *t = p->next; 419 printf("# 将作业%s投入到后备队列\n",p->jname); 420 AddHoubei(jobtable,p,jhead); 421 houbeinum++; //后背队列 422 tablenum--; //作业调度表 423 p = t; 424 } 425 else{ 426 p = p->next; 427 } 428 } 429 if(!isArrive){ 430 printf("# 无作业到达\n"); 431 } 432 433 //检查就绪队列是否已满。不满,则将后备队列队首放入就绪队列。 434 if(readynum==JOBNUM){ //已满 435 } 436 else{ //未满,从后备队列中将作业放入就绪队列 437 if(houbeinum!=0){ //后备队列不为空 438 CreateProcess(head,tail,jhead); //将作业投入到就绪队列 439 printf("# 将作业%s投入到就绪队列\n",jhead->jname); 440 jhead = jhead->next; //指向后备队列下一个作业 441 readynum++; //就绪队列 442 houbeinum--; //后备队列 443 } 444 //已空就算了 445 } 446 447 PCB* now = head; 448 if(now!=NULL){ //当前就绪队列不为空时运行进程 449 //将该进程放入运行队列 450 rhead = now; 451 //printf("将当前进程放入运行队列\n"); 452 453 printQueueInfo(jobtable,jhead,head,rhead,chead,tablenum,houbeinum,readynum); //打印所有队列信息 454 455 Work(now); //执行当前进程 456 457 if(now->time==0){ 458 now->status = ‘C‘; //设置进程为已完成状态 459 printf("# 进程%s已完成,退出就绪队列\n",now->pname); 460 DropPro(head,tail,chead,ctail); //推出循环就绪队列 461 readynum--; 462 if(readynum==0){ 463 head = 0; 464 tail = 0; 465 } 466 } 467 else{ 468 NextPro(head,tail); //已完成,将其置于循环队列尾端。即将head和tail向前推进一次 469 } 470 471 } 472 473 printQueueInfo2(head,chead,ctail,jhead,readynum); 474 475 getchar(); 476 477 } 478 479 curtime++; //计时+1 480 printf("当前系统时间 : %d\n",curtime); 481 482 printQueueInfo(jobtable,jhead,head,rhead,chead,tablenum,houbeinum,readynum); //打印所有队列信息 483 484 printQueueInfo2(head,chead,ctail,jhead,readynum); 485 486 return 0; 487 }
Freecode : www.cnblogs.com/yym2013