1 实验目的

分析处理器实施进程调度的前提条件,理解并掌握各类处理器调度算法设计原理和实现机制。


2 实验内容

分析和探索处理器实施进程调度的前提条件,理解并掌握处理器调度算法的设计原理和实现机制,随机发生和模拟进程创建及相关事件,编程实现基于特定处理器调度算法(三种以上,譬如先来先服务调度算法、短进程优先算法、高优先权优先调度算法、高响应比优先调度算法、时间片轮转调度算法、多级反馈队列调度算法、等等)的系统调度处理过程并加以测试验证。


3 实验要求

本实验课题主要功能设计要求包括:
1)选取和设计实现三种以上的处理器调度算法;
2)针对特定的处理器调度算法,分析处理器实施进程调度的前提条件和要求(譬如进程创建时刻、运 行时间长短、各集中计算运行/输入输出操作时间段长短、优先级),并随机发生和模拟处理对应的进 程创建及相关时间;
3)编程实现处理器调度机制,针对特定的处理器调度算法和随机事件序列,给出相应的调度处理过 程,主要涵盖进程相关时间、处理器调度操作或处理措施以及各状态进程列表;
4)测试验证处理器调度机制的有效性及有关处理器调度算法设计方案的正确性。


4 实验设计

4.1 随机生成模拟进程

该实验调度算法都采用python进行模拟,使用函数processList(num)生成模拟进程列表。主要使用python random模块随机生成进程到达时间,进程相对结束时间这两个数值。生成各进程参数如图注释所示。
OS: 处理器调度算法模拟实现与比较 - 图1
使用processShow(process)函数显示当前生成的进程列表,显示结果如图所示。
OS: 处理器调度算法模拟实现与比较 - 图2
OS: 处理器调度算法模拟实现与比较 - 图3


4.2 先来先服务调度算法

先来先服务调度算法是最基本的调度算法,核心是采用队列来实现。它根据进程到达时间决定先运行哪一个进程。这里我们使用list来实现。如下图所示,fcfs对模拟进程列表按时间到达先后进行排序。
OS: 处理器调度算法模拟实现与比较 - 图4
算法主体使用while循环来模拟,cputime模拟时间,代码大体梗概如图所示,需要注意的是,status函数用来输出当前进程列表状态,conclusion函数用于模拟结束后输出统计结果。
OS: 处理器调度算法模拟实现与比较 - 图5
Status函数:
OS: 处理器调度算法模拟实现与比较 - 图6
Conclusion函数:
OS: 处理器调度算法模拟实现与比较 - 图7
程序的main函数如图所示,通过传参将模拟方法与模拟进程数目传入。
OS: 处理器调度算法模拟实现与比较 - 图8
Fcfs调度算法模拟结果如图所示:
OS: 处理器调度算法模拟实现与比较 - 图9
OS: 处理器调度算法模拟实现与比较 - 图10


4.3 短进程优先调度算法

短进程优先调度算法是在先来先服务调度算法的基础上,对就绪进程所需要处理时间进行排序,优先服务短进程。所以模拟该调度算法也是在fcfs算法的基础上进行的,sjf算法新增加了对就绪队列排序的功能,使用sjfSort(process,current)函数实现,函数如图所示,使用选择排序对就绪进程队列按处理时间长短进行排序。
OS: 处理器调度算法模拟实现与比较 - 图11
模拟结果如图所示:
OS: 处理器调度算法模拟实现与比较 - 图12
OS: 处理器调度算法模拟实现与比较 - 图13


4.4 时间片轮转调度算法

时间片轮转调度算法的系统其进程就绪队列按照先来先服务调度原则,但是占用处理机只要一个时间片,在完成一个时间片后如果还没有完成就必须释放给下一个就绪的进程,而被剥夺的进程排到队尾。该算法最核心的便是时间片,在模拟程序中,我们将时间片长度设置为2s,while循环主体如图所示,与上两种算法有些不同,fcfs和sjf实现机制是普通队列,而rr调度算法实现机制是循环队列。
OS: 处理器调度算法模拟实现与比较 - 图14
RR调度算法运行结果如图所示:
OS: 处理器调度算法模拟实现与比较 - 图15
OS: 处理器调度算法模拟实现与比较 - 图16


4.5 高响应比优先调度算法

高响应比优先调度算法的基本思想是把CPU分配给就绪队列中响应比最高的进程。既考虑作业的执行时间也考虑作业的等待时间,综合了先来先服务和最短作业优先两种算法的特点。所以该代码大体也与sjf算法相似,不同的是排序的依据,hrrn算法通过计算响应比来对就绪进程排序。排序算法如图所示:
OS: 处理器调度算法模拟实现与比较 - 图17
HRRN算法运行结果如图所示:
OS: 处理器调度算法模拟实现与比较 - 图18
OS: 处理器调度算法模拟实现与比较 - 图19


4.6 调度算法简单比较

为了更好的体现各调度算法的特点,将模拟进程数设置为100.
FCFS算法:
OS: 处理器调度算法模拟实现与比较 - 图20
SJF算法:
OS: 处理器调度算法模拟实现与比较 - 图21
HRRN算法:
OS: 处理器调度算法模拟实现与比较 - 图22
RR算法:
OS: 处理器调度算法模拟实现与比较 - 图23
由于模拟生成的进程每一次程序运行都不一样,所以这里只简单分析各个算法点。
对于FCFS算法,100个模拟进程的带权周转时间,如果计算它们的方差,一定是特别大的。稳定性较差。
对于SJF算法和HRRN算法,各进程的带权周转时间在这里没有体现较大的差异,呈现出随到达时间增长进程的带权周转时间也增长的特点。猜测是random函数设置区间范围太小的原因。
最后对于RR算法,大体上各进程带权周转时间相近似,所以有比较好的稳定性。但是平均带权周转时间会有所增加。


5 实验总结

经过此次试验,对于操作系统的一些调度算法有了较为深刻的理解。对各调度算法的优点和缺点都有所了解,从而意识到了操作系统调度算法对于操作系统的重要性。

  1. import random,sys
  2. # 生成进程列表
  3. def processList(num):
  4. process=[]
  5. for i in range(num):
  6. dic={}
  7. dic['id']=i #模拟进程号
  8. dic['start']=random.randint(0,20) #进程到达时间
  9. dic['end']=dic['start']+random.randint(1,20) #进程相对结束时间
  10. dic['runtime']=dic['end']-dic['start'] #进程所需运行时间
  11. dic['status']="" #进程当前状态
  12. dic['left']=dic['runtime'] #进程运行剩余时间
  13. dic['wait_time']=0 #进程等待时间
  14. dic['tr_time']=0 #进程周转时间
  15. process.append(dic)
  16. return process
  17. # 展示进程列表
  18. def processShow(process):
  19. for p in process:
  20. print(p)
  21. print()
  22. # 展示当前状态
  23. def status(process):
  24. print("-----status table-------")
  25. for p in process:
  26. print("process id:%d status:%s"%(p['id'],p['status']))
  27. print()
  28. # 计算进程状态时间
  29. def conclusion(process):
  30. print("-------------conclusion table--------------")
  31. print("进程ID 等待时间 周转时间 带权周转时间|")
  32. sum1=0
  33. sum2=0
  34. sum3=0.0
  35. for p in process:
  36. wait_time=p['wait_time']
  37. sum1+=wait_time
  38. tr_time=p['tr_time']
  39. sum2+=tr_time
  40. wtr_time=float(p['tr_time'])/(p['end']-p['start'])
  41. sum3+=wtr_time
  42. print("%3d %3ds %3ds %5.2f |"%(p['id'],p['wait_time'],p['tr_time'],wtr_time))
  43. print("-------------------------------------------")
  44. print("平均等待时间: %ds\n平均周转时间: %ds\n平均带权周转时间:%.2fs"%(sum1/len(process),sum2/len(process),sum3/len(process)))
  45. print("-------------------------------------------")
  46. # 非抢占式就绪排序
  47. def sjfSort(process,current):
  48. for i in range(current,len(process)):
  49. min=i
  50. for j in range(current+1,len(process)):
  51. if process[i]['status'] =='就绪' and process[j]['status']=='就绪':
  52. if process[min]['runtime']>process[j]['runtime']:
  53. min=j
  54. process[min],process[i]=process[i],process[min]
  55. return process
  56. # 高响应比排序
  57. def hrrnSort(process,current,cputime):
  58. for i in range(current,len(process)):
  59. min=i
  60. for j in range(current+1,len(process)):
  61. if process[i]['status'] =='就绪' and process[j]['status']=='就绪':
  62. scale_j=float(cputime-process[j]['start']+process[j]['runtime'])/process[j]['runtime']
  63. scale_min=float(cputime-process[min]['start']+process[min]['runtime'])/process[min]['runtime']
  64. if scale_j>scale_min:
  65. min=j
  66. process[min],process[i]=process[i],process[min]
  67. return process
  68. # 先来先服务算法
  69. def FCFS(process):
  70. print("-------------------------------FCFS-----------------------------")
  71. process=sorted(process,key=lambda x:x['start'])
  72. processShow(process)
  73. cputime=0
  74. current=0
  75. while True:
  76. flag=False
  77. if process[0]['start']==cputime:
  78. process[current]['runtime']+=cputime
  79. process[current]['status']="运行"
  80. process[current]['wait_time']=cputime-process[current]['start']
  81. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  82. flag=True
  83. #当前进程结束
  84. if current<=len(process) and process[current]['runtime']==cputime and process[current]['status']=='运行':
  85. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"结束!")
  86. process[current]['status']='Die'
  87. process[current]['tr_time']=cputime-process[current]['start']
  88. flag=True
  89. #所有进程结束
  90. if process[current]['status']=='Die' and current==len(process)-1:
  91. print("所有进程执行完毕,总计耗时"+str(cputime)+"s")
  92. conclusion(process)
  93. break;
  94. #新进程开始
  95. if process[current]['status']=='Die' and process[current+1]['start']<=cputime:
  96. current+=1
  97. process[current]['runtime']+=cputime
  98. process[current]['status']="运行"
  99. process[current]['wait_time']=cputime-process[current]['start']
  100. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  101. flag=True
  102. #检查是否有新进程到达
  103. for i in range(current+1,len(process)):
  104. if process[i]['start'] == cputime:
  105. process[i]['status'] = "就绪"
  106. if flag:
  107. status(process)
  108. cputime+=1
  109. # 非抢占式短作业优先算法
  110. def SJF(process):
  111. print("-------------------SJF------------------------------------")
  112. process=sorted(process,key=lambda x:x['start'])
  113. processShow(process)
  114. cputime=0
  115. current=0
  116. while True:
  117. flag=False
  118. if process[0]['start']==cputime:
  119. process[current]['runtime']+=cputime
  120. process[current]['status']="运行"
  121. process[current]['wait_time']=cputime-process[current]['start']
  122. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  123. flag=True
  124. if current<=len(process) and process[current]['runtime']==cputime:
  125. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"结束!")
  126. process[current]['status']='Die'
  127. process[current]['tr_time']=cputime-process[current]['start']
  128. flag=True
  129. if process[current]['status']=='Die' and current==len(process)-1:
  130. print("所有进程执行完毕,总计耗时"+str(cputime)+"s")
  131. conclusion(process)
  132. break;
  133. if process[current]['status']=='Die' and process[current+1]['start']<=cputime:
  134. current+=1
  135. process[current]['runtime']+=cputime
  136. process[current]['status']="运行"
  137. process[current]['wait_time']=cputime-process[current]['start']
  138. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  139. flag=True
  140. for i in range(current+1,len(process)):
  141. if process[i]['start'] == cputime:
  142. process[i]['status'] = "就绪"
  143. process=sjfSort(process,current+1)
  144. if flag:
  145. status(process)
  146. cputime+=1
  147. # 时间片轮询调度算法
  148. def RR(process):
  149. print("-------------------RR------------------------------------")
  150. process=sorted(process,key=lambda x:x['start'])
  151. processShow(process)
  152. cputime=0
  153. time_slice=2
  154. current=0
  155. start=True
  156. while True:
  157. flag=False
  158. if start:
  159. if time_slice==0:
  160. time_slice==2
  161. if process[0]['start']==cputime:
  162. process[0]['status']='运行'
  163. print("第"+str(cputime)+ "s"+"进程"+str(process[0]['id'])+"开始!")
  164. flag=True
  165. start=False
  166. #当前进程运行结束
  167. if process[current]['status']=='运行' and process[current]['left']==0:
  168. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"结束!")
  169. process[current]['status']='Die'
  170. process[current]['tr_time']=cputime-process[current]['start']
  171. process[current]['wait_time']=process[current]['tr_time']-process[current]['runtime']
  172. flag=True
  173. sig=True
  174. #启用新进程或所有进程结束
  175. if process[current]['status']=='Die':
  176. for i in range(current+1,current+len(process)):
  177. if process[i%len(process)]['status']=='就绪':
  178. process[i%len(process)]['status']='运行'
  179. current=i%len(process)
  180. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  181. sig=False
  182. flag=True
  183. break
  184. if sig:
  185. sig=True
  186. for i in range(len(process)):
  187. if process[i]['status']!='Die':
  188. sig=False
  189. break
  190. if sig:
  191. status(process)
  192. print("所有进程执行完毕,总计耗时"+str(cputime)+"s")
  193. conclusion(process)
  194. break
  195. if time_slice==0:
  196. time_slice=2
  197. #时间片结束,切换进程执行
  198. if (not start) and time_slice==0:
  199. process[current]['status']='就绪'
  200. time_slice=2
  201. for i in range((current+1)%len(process),(current+len(process))+1):
  202. if process[i%len(process)]['status']=='就绪':
  203. process[i%len(process)]['status']='运行'
  204. current=i%len(process)
  205. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  206. flag=True
  207. break
  208. for i in range(current+1,len(process)):
  209. if process[i]['start'] == cputime:
  210. process[i]['status'] = "就绪"
  211. if flag:
  212. status(process)
  213. cputime+=1
  214. if not start:
  215. process[current]['left']-=1
  216. time_slice-=1
  217. # 高响应比优先算法
  218. def HRRN(process):
  219. print("-------------------HRRN------------------------------------")
  220. process=sorted(process,key=lambda x:x['start'])
  221. processShow(process)
  222. cputime=0
  223. current=0
  224. while True:
  225. flag=False
  226. if process[0]['start']==cputime:
  227. process[current]['runtime']+=cputime
  228. process[current]['status']="运行"
  229. process[current]['wait_time']=cputime-process[current]['start']
  230. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  231. flag=True
  232. if current<=len(process) and process[current]['runtime']==cputime:
  233. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"结束!")
  234. process[current]['status']='Die'
  235. process[current]['tr_time']=cputime-process[current]['start']
  236. flag=True
  237. if process[current]['status']=='Die' and current==len(process)-1:
  238. print("所有进程执行完毕,总计耗时"+str(cputime)+"s")
  239. conclusion(process)
  240. break;
  241. if process[current]['status']=='Die' and process[current+1]['start']<=cputime:
  242. current+=1
  243. process[current]['runtime']+=cputime
  244. process[current]['status']="运行"
  245. process[current]['wait_time']=cputime-process[current]['start']
  246. print("第"+str(cputime)+ "s"+"进程"+str(process[current]['id'])+"开始!")
  247. flag=True
  248. for i in range(current+1,len(process)):
  249. if process[i]['start'] == cputime:
  250. process[i]['status'] = "就绪"
  251. process=hrrnSort(process,current+1,cputime)
  252. if flag:
  253. status(process)
  254. cputime+=1
  255. if __name__=="__main__":
  256. if len(sys.argv)<3:
  257. print("need more parameter!")
  258. exit()
  259. process=processList(int(sys.argv[2]))
  260. cmd=sys.argv[1].upper()
  261. if cmd=="FCFS":
  262. FCFS(process)
  263. elif cmd=="SJF":
  264. SJF(process)
  265. elif cmd=="RR":
  266. RR(process)
  267. elif cmd=="HRRN":
  268. HRRN(process)
  269. else:
  270. print("unknown command!")