操作系统实验—处理机调度算法的模拟
操作系统实验—处理机调度算法的模拟一、实验目的:二、实验内容:PCB进程控制块结构设计要求:三、实验过程记录:1、算法的思路2、主要数据结构3、程序代码运行效果一、实验目的:熟悉处理器调度算法的工作原理,掌握调度算法的实现、进程的状态及状态转换。具体如下:设计并实现模拟进程调度的算法:时间片轮转调度算法。理解进程控制块的结构。理解进程运行的并发性。掌握进程调度算法。二、实验内容:在多道程序运行环境
一、实验目的:
熟悉处理器调度算法的工作原理,掌握调度算法的实现、进程的状态及状态转换。具体如下:
- 设计并实现模拟进程调度的算法:时间片轮转调度算法。
- 理解进程控制块的结构。
- 理解进程运行的并发性。
- 掌握进程调度算法。
二、实验内容:
在多道程序运行环境下,进程数目一般多于处理机数目,使得进程要通过竞争来使用处理机。这就要求系统能按某种算法,动态地把处理机分配给就绪队列中的一个进程,使之运行,分配处理机的任务是由进程调度程序完成的。一个进程被创建后,系统为了便于对进程进行管理,将系统中的所有进程按其状态,将其组织成不同的进程队列。于是系统中有运行进程队列、就绪队列和各种事件的进程等待队列。进程调度的功能就是从就绪队列中挑选一个进程到处理机上运行。进程调度的算法有多种,常用的有优先级调度算法、先来先服务算法、时间片轮转算法。
进程是程序在处理机上的执行过程。进程存在的标识是进程控制块
PCB进程控制块结构
typedef struct PCB
{
int id; /* 进程id */
char name[10]; /* 进程标识符 */
int allTime; /* 进程共需要占用 CPU 时间 */
int needTime; /* 进程到完成还需要的时间 */
int cpuTime; /* 进程已经占用CPU的时间 */
int startBlock; /* 开始阻塞的时刻,-1表示不会发生阻塞*/
int blockTime; /* 阻塞消耗的总时间 */
char state; /* 进程的状态:就绪、阻塞、运行、完成*/
struct node *next /*链指针*/
}PCB;
系统创建一个进程,就是由系统为某个程序设置一个PCB,用于对该进程进行控制和管理,进程任务完成,由系统收回其PCB,该进程便消亡。每个进程可以有四个状态:运行状态、就绪状态、阻塞状态和完成状态。
用C语言编写一个程序实现进程调度的算法,模拟进程调度的过程,加深对进程控制块概念和进程调度算法的理解。
设计要求:
- 进程的调度采用时间片轮转算法。
- 设计3个链队列,分别用来表示就绪队列、阻塞队列和完成队列。
- 进程的相关信息通过一个文本文件的形式传给程序,程序在接受到进程的信息后,为每个进程申请空间并存放进进程控制块PCB中。文本文件的内容自行设置。
- 为了清楚的观察各个进程的调度过程,每当有进程状态变化时,程序应该将所有进程当前的状态显示出来,一直到所有进程运行完成为止。具体参照如下的格式:
各个就绪进程的信息如下:
时间片轮转调度的基本原理:系统将所有就绪的进程按先来先服务的原则排成一个就绪队列。系统设置每一个时间间隔便产生一次中断,去激活进程调度程序进行调度,把CPU分配给队首进程,并令其执行一个时间片。当它运行完毕后,又把处理机分配给就绪队列中新的队首进程,也让它执行一个时间片。这样,就可以保证就绪队列中的所有进程在确定的时间段内,都能获得一个时间片的处理机时间。
在时间片轮转调度算法中,触发进程调度有如下几种情况:○1若一个时间片尚未用完,正在运行的进程便已经完成,就会立即激活调度程序,将它从就绪队列中删除,再调度就绪队列的队首进程运行。○2在一个时间片用完时,计时器中断处理程序被激活;如果进程尚未运行完毕,调度程序就把它送到就绪队列的末尾,再调度就绪队列的队首进程运行。○3进程在运行过程中遇到事件需要阻塞,这时即把该进程的状态由运行改为阻塞并置入事件阻塞队列末尾,然后激活调度程序,调度就绪队列的队首进程运行。○4在进程的阻塞事件完成后,向系统发送阻塞完成的信息,系统在收到相关信息后,就把该进程从阻塞队列中删除并置入就绪队列末尾。
三、实验过程记录:
1、算法的思路
首先实现本算法需要用到PCB以及PCB队列两个主要数据结构,编写函数实现PCBQueue的增删以及输出,还要实现对PCB控制块赋值的代码。通过对文件的操作封装readFile方法,获取txt文件中的数据对PCBQueue初始化,根据要求格式化输出。最后根据时间片轮转调度算法对进程进行模拟操作,输出每次运行的结果。
2、主要数据结构
PCB结构体
1. typedef struct PCB
2. {
3. int id; /* 进程id */
4. string name; /* 进程标识符 */
5. int allTime; /* 进程共需要占用 CPU 时间 */
6. int needTime; /* 进程到完成还需要的时间 */
7. int cpuTime; /* 进程已经占用CPU的时间 */
8. int startBlock; /* 开始阻塞的时刻,-示不会发生阻塞*/
9. int blockTime; /* 阻塞消耗的总时间 */
10. string state;/* 进程的状态:就绪、阻塞、运行、完成*/
11. int blockT=//已经阻塞的时间
12. PCB *next; /*链指针*/
13. } PCB;
PCB队列结构体
14. struct PCBQueue{
15. PCB *head=NULL;
16. PCB *end=NULL;
17. };
18. void addPCB(PCBQueue &q,PCB *next){
19. if(q.head==NULL){
20. q.head=q.end=next;
21. return;
22. }
23. next->next=NULL;
24. q.end->next=next;
25. q.end=next;
26. }
27.
28. PCB* deletePCBQueue(PCBQueue &q){
29. PCB *p=q.head;
30. if(q.head->next==NULL){
31. q.head=NULL;
32. q.end=NULL;
33. }else{
34. q.head=q.head->next;
35. }
36. p->next=NULL;
37. return p;
38. }
39. void PrintPCBQueue(PCBQueue &q){
40. if(q.head==NULL)
41. return;
42. PCB *p=q.head;
43. while(p!=q.end){
44. cout<<"id"<<p->id<<" -> ";
45. p=p->next;
46. }
47. cout<<"id"<<p->id;
48. }
主要数据结构为进程控制块PCB的结构体以及对他进行操作的函数
3、程序代码
1. #include <iostream>
2. #include <queue>
3. #include <fstream>
4. #define TIMESLICE 5
5. using namespace std;
6.
7. typedef struct PCB
8. {
9. int id; /* 进程id */
10. string name; /* 进程标识符 */
11. int allTime; /* 进程共需要占用 CPU 时间 */
12. int needTime; /* 进程到完成还需要的时间 */
13. int cpuTime; /* 进程已经占用CPU的时间 */
14. int startBlock; /* 开始阻塞的时刻,-1表示不会发生阻塞*/
15. int blockTime; /* 阻塞消耗的总时间 */
16. string state;/* 进程的状态:就绪、阻塞、运行、完成*/
17. int blockT=0;//已经阻塞的时间
18. PCB *next; /*链指针*/
19. } PCB;
20. struct PCBQueue{
21. PCB *head=NULL;
22. PCB *end=NULL;
23. };
24. void addPCB(PCBQueue &q,PCB *next){
25. if(q.head==NULL){
26. q.head=q.end=next;
27. return;
28. }
29. next->next=NULL;
30. q.end->next=next;
31. q.end=next;
32. }
33.
34. PCB* deletePCBQueue(PCBQueue &q){
35. PCB *p=q.head;
36. if(q.head->next==NULL){
37. q.head=NULL;
38. q.end=NULL;
39. }else{
40. q.head=q.head->next;
41. }
42. p->next=NULL;
43. return p;
44. }
45. void PrintPCBQueue(PCBQueue &q){
46. if(q.head==NULL)
47. return;
48. PCB *p=q.head;
49. while(p!=q.end){
50. cout<<"id"<<p->id<<" -> ";
51. p=p->next;
52. }
53. cout<<"id"<<p->id;
54. }
55. PCB initialize(int id,string name,int allTime,int needTime,int cpuTime,int startBlock,int blockTime,string state,struct PCB *next){
56. PCB p;
57. p.id=id;
58. p.name=name;
59. p.allTime=allTime;
60. p.needTime=needTime;
61. p.cpuTime=cpuTime;
62. p.startBlock=startBlock;
63. p.blockTime=blockTime;
64. p.state=state;
65. p.next=next;
66. p.blockT=0;
67. return p;
68. }
69. void readFile(PCB p[6]){
70. ifstream outfile("C:\\Users\\社会人\\Desktop\\操作系统\\data.txt");
71. int id;string name;int allTime;int needTime;int cpuTime;int startBlock;int blockTime;string state;
72. int time=0;
73. while(outfile>>id>>name>>allTime>>needTime>>cpuTime>>startBlock>>blockTime>>state){
74. p[time]=initialize(id,name,allTime,needTime,cpuTime,startBlock,blockTime,state,NULL);
75. time++;
76. }
77. outfile.close();
78. }
79. void printFirstPCB(PCB p[6],PCBQueue readPCB){
80. cout<<"程序开始:"<<endl; /* 用整数表示的时间,开始时为0 */
81. cout<<"当前时间:"<<0<<endl;
82. cout<<"各个就绪进程的信息如下:"<<endl;
83. cout<<"就绪队列:";
84. PrintPCBQueue(readPCB);
85. cout<<endl; /* 显示就绪队列所有的进程,假设系统开始有6个进程 */
86. cout<<"========================================================================"<<endl;
87. cout<<" id name allTime needTime cpuTime startBlock blockTime state"<<endl;
88. cout<<"------------------------------------------------------------------------"<<endl;
89. for(int i=0;i<6;i++){
90. printf(" %d\t %s\t\t\t%d\t\t%d\t\t\t%d\t\t%d\t\t\t%d\t\t%s\n",p[i].id,p[i].name.c_str(),p[i].allTime,p[i].needTime,p[i].cpuTime,p[i].startBlock,p[i].blockTime,p[i].state.c_str());
91. }
92. cout<<"------------------------------------------------------------------------"<<endl;
93. }
94. void printPCB(PCB p[6],int t,int m,PCBQueue readPCB,PCBQueue blockPCB,PCBQueue completPCB){
95. cout<<"第"<<t<<"次有程序状态变化:"<<endl;
96. cout<<"当前时间:"<<m<<endl; /* 用整数表示的时间,开始时为0 */
97. cout<<"运行状态程序:id, name, allTime, needTime, cpuTime, startBlock, blockTime, state"<<endl;
98. cout<<"就绪队列:";
99. PrintPCBQueue(readPCB);/* 显示就绪队列所有的进程 */
100. cout<<endl;
101. cout<<"阻塞队列:";
102. PrintPCBQueue(blockPCB);
103. cout<<endl;
104. /* 显示阻塞队列所有的进程 */
105. cout<<"完成队列:";
106. PrintPCBQueue(completPCB);/* 显示完成队列所有的进程 */
107. cout<<endl;
108. cout<<"========================================================================"<<endl;
109. cout<<" id name allTime needTime cpuTime startBlock blockTime state"<<endl;
110. cout<<"------------------------------------------------------------------------"<<endl;
111. for(int i=0;i<6;i++){
112. printf(" %d\t %s\t\t\t%d\t\t%d\t\t\t%d\t\t%d\t\t\t%d\t\t%s\n",p[i].id,p[i].name.c_str(),p[i].allTime,p[i].needTime,p[i].cpuTime,p[i].startBlock,p[i].blockTime,p[i].state.c_str());
113. }
114. cout<<"------------------------------------------------------------------------"<<endl;
115. }
116. void SchedulingAlgorithm(PCB p[6],int m,int t,PCBQueue readPCB,PCBQueue blockPCB,PCBQueue completPCB){
117. PCB *readp=NULL;
118. bool flag;
119. int readTime;
120. while(readPCB.head!=NULL||blockPCB.head!=NULL){
121. if(readPCB.head==NULL){
122. PCB *blockP=deletePCBQueue(blockPCB);
123. m+=blockP->blockTime-blockP->blockT;
124. blockP->blockT=0;
125. blockP->state="READY";
126. addPCB(readPCB,blockP);
127. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
128. }
129. if(readPCB.head!=NULL){
130. readp=deletePCBQueue(readPCB);
131. readp->state="RUNNING";
132. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
133. flag=false;
134. readTime=0;
135. if(readp->startBlock!=-1){
136. if(readp->startBlock<=TIMESLICE){
137. if(readp->needTime<=readp->startBlock){//运行完
138. readTime+=readp->needTime;
139. m+=readp->needTime;
140. readp->cpuTime+=readp->needTime;
141. readp->needTime=0;
142. readp->state="FINISHED";
143. addPCB(completPCB,readp);
144. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
145. }else{//阻塞
146. readTime+=readp->startBlock;
147. m+=readp->startBlock;
148. readp->cpuTime+=readp->startBlock;
149. readp->needTime-=readp->startBlock;
150. readp->state="BLOCKED";
151. readp->startBlock=-1;
152. }
153. }else
154. flag=true;
155. }else
156. flag=true;
157. if(flag){//正常运行
158. if(readp->needTime<=TIMESLICE){//运行完
159. readTime+=readp->needTime;
160. m+=readp->needTime;
161. readp->cpuTime+=readp->needTime;
162. readp->needTime=0;
163. readp->state="FINISHED";
164. addPCB(completPCB,readp);
165. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
166. }else{//没有运行完
167. readTime+=TIMESLICE;
168. readp->cpuTime+=TIMESLICE;
169. readp->needTime-=TIMESLICE;
170. readp->state="READY";
171. m+=TIMESLICE;
172. addPCB(readPCB,readp);
173. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
174. }
175. }
176. }
177. while(blockPCB.head!=NULL&&readp!=NULL){
178. PCB *blockP=deletePCBQueue(blockPCB);
179. if(readTime==0)
180. break;
181. if(blockP->blockTime-blockP->blockT>readTime){//时间用完
182. readTime=0;
183. blockP->blockT+=readTime;
184. break;
185. }else{//阻塞结束
186. readTime-=(blockP->blockTime-blockP->blockT);
187. blockP->blockT=0;
188. blockP->state="READY";
189. addPCB(readPCB,blockP);
190. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
191. }
192. }
193. if(readp->state=="BLOCKED"){
194. addPCB(blockPCB,readp);
195. printPCB(p,t++,m,readPCB,blockPCB,completPCB);
196. }
197. }
198. }
199. int main(){
200. PCB p[6],*readp;
201. readFile(p);
202. int m=0,t=1;//时间和次数
203. PCBQueue readPCB,blockPCB,completPCB;//就绪 阻塞 完成
204. for(int i=0;i<6;i++){
205. addPCB(readPCB,&p[i]);
206. }
207. printFirstPCB(p,readPCB);
208. SchedulingAlgorithm(p,m,t,readPCB,blockPCB,completPCB);
209. }
运行效果
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)