呓语 | 杨英明的个人博客

专注于c++、Python,欢迎交流

By

《操作系统》实验之进程调度

实验内容:

第一部分:作业调度

   作业名

要求运行时间

   优先级

  到达时间

  链接指针

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
# 后备队列:
=>------------------------------------------------------
View Code

源代码:

  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

##原创声明 **转载请注明:[呓语](http://www.yangyingming.com) » [《操作系统》实验之进程调度](http://www.yangyingming.com/article/34)**