进程调度-操作系统

敬请T期待 Lv3

进程调度

实验说明

实验目的

进一步理解进程调度的过程

理解先来先服务FCFS、简单时间片轮转、动态优先级调度算法的基本原理

实验内容

编写一个C或C++代码,实现以上要求的算法(至少完成2个算法),每进行一次调度,打印一次运行进程、就绪队列,以及每个进程的PCB信息。

实现环境:windows 、Linux

输入及输出

程序开始时,输入进程的个数,每个进程的名称、到达时间、服务时间、初始优先级(值越大,优先级越高)

选择一个调度算法,开始运行;

每进行一次调度,显示当前正在运行的进程名称、就绪队列中的进程名称(按顺序),以及当前所有进程的信息。

每个进程用一个进程PCB来表示,一般包括进程名(10个字符)、到达时间、服务时间、已用时间、优先数、进程状态(运行、就绪、完成)

进程到达、服务、已用时间均为时间片

FCFS 调度算法:按照进程到达时间,依次调度,每个进程结束后,调度下一个进程。

时间片轮转算法:每个进程完成一个时间片后,放弃处理机,转到就绪队列队尾(不考虑优先级)

动态优先级:每个进程完成一个时间片后,优先级减1,插入到就绪队列相关位置(队列头是优先级最高的进程),每次调度,选择优先级最高的队列运行。

实验代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <queue>
using namespace std;
//进程三种状态,这里增加一种,表示虽然输入,但是还没有到达进入系统时刻typedef enum ProcessState{Executing, Ready, Finish, Unarrive}STATE;
typedef struct process_pcb
{
int ID; //进程标识
int priority; //进程优先数,值越大,优先级越高
int arrive_time; //进程到达时间,以时间片为单位
int service_time; //进程需要总的服务时间
int start_time; //进程开始执行时间
int end_time; //进程结束时间
int all_time; //进程仍然需要运行时间
int cpu_time; //进程已占用cpu时间
const char* state; //进程状态
}PCB;
//用于打印进程三种状态
const char* StateString[] = { "Executing","Ready","Finish","--" };
//排序比较函数:按照进程到达时间升序排列
bool cmp_arrive_time(const PCB a, const PCB b);
//排序比较函数:按照进程优先数降序排序
bool cmp_priority(const PCB a, const PCB b);

void input_process(); //输入进程信息
int select_policy(); //选择进程调度策略
void print_all(int current); //打印所有进程信息
void FCFS(); //先来先服务算法
void round_robin(); //时间片轮转算法
void dynamic_prio(); //动态优先级算法

PCB* running_process = NULL;//当前运行任务
//进程到达队列,如进程还没到到达时间,则该进程仍然在到达队列中
vector<PCB> arrive_queue;
vector<PCB> ready_queue;//就绪队列
vector<PCB> finish_queue;//完成队列
int main()
{
printf("===================================================\n");
printf(" 操作系统进程调度模拟实验 \n");
printf("===================================================\n");
printf("\n");
input_process();
print_all(-1); //打印进程的初始状态
int policy = select_policy();
switch (policy)
{
case 1:
FCFS();
break;
case 2:
round_robin();
break;
case 3:
dynamic_prio();
break;
default:
FCFS();
break;
}
}
//按进程到达时间升序排列,先到达的排在队首
bool cmp_arrive_time(const PCB a, const PCB b)
{
return a.arrive_time < b.arrive_time;
}
//按进程优先级降序排列,优先级高的排在队首
//如优先级相同,先到的进程排在前面
bool cmp_priority(const PCB a, const PCB b)
{
if (a.priority != b.priority) {
return a.priority > b.priority;
}
else {
return a.arrive_time < b.arrive_time;
}
}
//选择进程调度策略
int select_policy()
{
printf("\n请选择调度算法(输入、、选择):\n");
printf("1.先来先服务调度(FCFS) \n");
printf("2.时间片轮转调度(Round-Robin) \n");
printf("3.动态优先级调度(DynamicPriority) \n");
int n;
printf("请输入调度算法序号:");
while (scanf_s("%d", &n)) {
if (n > 3 || n < 1) {
printf("对不起,输入有误,请重新输入!\n");
}
else {
break;
}
}
return n;
}
//输入进程信息
void input_process()
{
int num;
printf("请输入进程数量:");
scanf_s("%d", &num);
PCB pro;
for (int i = 1; i <= num; i++) {
printf("\n请输入第%d个进程的到达时间、服务时间及优先级(以空格隔开):\n", i);
scanf_s("%d%d%d", &pro.arrive_time, &pro.service_time, &pro.priority);
pro.ID = i;
pro.all_time = pro.service_time;
pro.cpu_time = 0;
pro.start_time = -1;//开始时间、结束时间默认为-1,表示尚未被调度过
pro.end_time = -1;
pro.state = "Unarrive";//初始化为尚未进入到达
arrive_queue.push_back(pro);
}
//按照到达时间升序排队
sort(arrive_queue.begin(), arrive_queue.end(), cmp_arrive_time);
}
//打印单个进程的信息
void print_process(PCB* pro)
{
if (pro == NULL) {
return;
}
printf("%4d%10d%10d%8d%10s", pro->ID, pro->arrive_time, pro->service_time, pro->priority, pro->state);
if (pro->start_time == -1) {//开始时间,结束时间,剩余时间
printf("%10s%10s%10s", "--", "--", "--");
}
else {
if (pro->end_time == -1) {
printf("%10d%10s%10d", pro->start_time, "--", pro->all_time);
}
else {
printf("%10d%10d%10d", pro->start_time, pro->end_time, pro->all_time);
}
}
if (pro->state == "Finish")//周转时间及带权周转时间
{
printf("%10d%10.2lf\n", pro->end_time - pro->arrive_time, (float)(pro->end_time - pro->arrive_time) / (float)pro->service_time);
}
else {
printf("%10s%10s\n", "--", "--");
}
}
//打印所有进程的信息
void print_all(int current)
{
if (current == -1) {
printf("\n进程初始状态:\n", current);
}
else {
printf("\n当前时刻为:%d\n", current);
}
printf("进程号 到达时间 服务时间 优先级 状态 开始时间 结束时间 剩余时间 周转时间 带权周转时间\n");
//首先打印正在运行的进程
if (running_process != NULL) {
print_process(running_process);
}
vector<PCB>::iterator it;
//然后打印就绪队列中的进程
for (it = ready_queue.begin(); it != ready_queue.end(); it++) {
print_process(&(*it));
}
//然后打印完成队列中的进程
for (it = finish_queue.begin(); it != finish_queue.end(); it++) {
print_process(&(*it));
}
//然后打印仍然在到达队列中的进程
for (it = arrive_queue.begin(); it != arrive_queue.end(); it++) {
print_process(&(*it));
}
}
//先来先服务算法
void FCFS()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while (1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if (!running_process && arrive_queue.empty() && ready_queue.empty()) {
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while (!arrive_queue.empty()) {
PCB pro = arrive_queue[0];
if (pro.arrive_time <= chip) {
pro.state = "Ready";
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}
else {
break;
}
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if (need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
running_process->start_time = chip;
running_process->state = "Executing";
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//FCFS当前任务运行到结束,才可能调度下一个任务
if (running_process) {
running_process->end_time = running_process->start_time + running_process->service_time;
running_process->state = "Finish";
running_process->cpu_time = running_process->service_time;
running_process->all_time = 0;
chip += running_process->service_time;
finish_queue.push_back(*running_process);//将完成任务放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {
chip += 1;
}
}
//所有任务全部完成后,打印一次
print_all(chip);
}
//时间片轮转算法
void round_robin()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while (1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if (!running_process && arrive_queue.empty() && ready_queue.empty()) {
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while (!arrive_queue.empty()) {
PCB pro = arrive_queue[0];
if (pro.arrive_time <= chip) {
pro.state = "Ready";
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}
else {
break;
}
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if (need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
if (running_process->start_time == -1) {//首次运行
running_process->start_time = chip;
}
running_process->state = "Executing";
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//当前运行任务完成个时间片,判断该任务是否已经完成
if (running_process) {
running_process->cpu_time += 1;
running_process->all_time -= 1;
if (running_process->all_time == 0) {//任务运行结束
running_process->end_time = chip + 1;
running_process->state = "Finish";
finish_queue.push_back(*running_process);//将其放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {//任务没有完成,如果就绪队列中仍有任务,则轮转调度,否则不调度(这里是一种调度的优化,避免重新调度开销)
if (!ready_queue.empty()) {
running_process->state = "Ready";
ready_queue.push_back(*running_process);//将其放回就绪队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {
need_schedule = false;
}
}
}
chip += 1;
}
//所有任务全部完成后,打印一次
print_all(chip);
}
//动态优先级算法
void dynamic_prio()
{
int chip = 0;//初始的时间片为0
bool need_schedule = true;
while (1)
{
//如果到达队列和就绪队列都为空,则所有进程完成
if (!running_process && arrive_queue.empty() && ready_queue.empty()) {
break;
}
//将到达队列中,到达时间为当前时间片的进程放入就绪队列中,并从到达队列中删除
while (!arrive_queue.empty()) {
PCB pro = arrive_queue[0];
if (pro.arrive_time <= chip) {
pro.state = "Ready";
ready_queue.push_back(pro);
arrive_queue.erase(arrive_queue.begin() + 0);
}
else {
break;
}
}
if (!ready_queue.empty()) {
//将就绪进程按照优先级降序排列
sort(ready_queue.begin(), ready_queue.end(), cmp_priority);
}
//判断是否需要调度,如需要就从就绪队列中拿出一个进行调度
if (need_schedule && !ready_queue.empty())
{
running_process = new PCB;
*running_process = ready_queue[0];//从就绪队首中取出一个
ready_queue.erase(ready_queue.begin() + 0);//从就绪队列中删除之
//调度一个程序开始运行
if (running_process->start_time == -1) {//首次运行
running_process->start_time = chip;
}
running_process->state = "Executing";
need_schedule = false;
print_all(chip);//打印当前所有进程的信息
}
//当前运行任务完成个时间片,判断该任务是否已经完成
if (running_process) {
running_process->cpu_time += 1;
running_process->all_time -= 1;
if (running_process->all_time == 0) {//任务运行结束
running_process->end_time = chip + 1;
running_process->state = "Finish";
finish_queue.push_back(*running_process);//将其放入完成队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {//任务没有完成,如果就绪队列中仍有任务,且优先级大于或等于本任务的优先级,则轮转调度,否则不调度
if (running_process->priority > 1) {
running_process->priority -= 1;//优先级最小为1
}
if (!ready_queue.empty() && ready_queue[0].priority >= running_process->priority) {
running_process->state = "Ready";
ready_queue.push_back(*running_process);//将其放回就绪队列中
delete running_process;
running_process = NULL;
need_schedule = true;
}
else {
need_schedule = false;
}
}
}
chip += 1;
}
//所有任务全部完成后,打印一次
print_all(chip);
}

实验结果:

process
  • Title: 进程调度-操作系统
  • Author: 敬请T期待
  • Created at : 2024-10-19 19:51:40
  • Updated at : 2024-10-19 20:04:09
  • Link: https://kingwempity.github.io/2024/10/19/进程调度-操作系统/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments