一、文章概述
文章根据已给条件(实验课老师给的)对进程调度算法进行分析,应用范围有限,但可以初步了解进程调度算法,由于本人学识浅薄,文章中难免有不足和错误之处,恳请读者批评指正。
实验内容如下:
二、进程调度算法
首先定义一下进程的控制信息:
#define max 50
struct PCB
{
int name;
int arrivetime; //到达时间
int servicetime; //服务时间
int finishtime; //完成结束时间
int turntime; //周转时间
int weight_turntime; //带权周转时间
int sign; //标志进程是否完成
int remain_time; //剩余时间
int priority; //优先级
}pcb[max];//进程控制块数组,其中每个元素代表一个进程,并包含诸如到达时间(arrivetime)、剩余时间(remain_time)、完成时间(finishtime)等属性。注:下标从1开始
int main() {
int n;
printf("input the number of process\n");
scanf("%d", &n);
init(n);//初始化进程
creat(n);//创建进程
layout(n);//选择相应的调度算法
return 0;
}
void init(int n) //初始化
{
int i;
for (i = 0; i <= n; i++)//元素均初始化为0
{
pcb[i].arrivetime = 0;
pcb[i].servicetime = 0;
pcb[i].starttime = 0;
pcb[i].finishtime = 0;
pcb[i].turntime = 0;
pcb[i].weight_turntime = 0;
pcb[i].remain_time = 0;
pcb[i].sign = 0;
pcb[i].priority = 0;
}
}
void creat(int n) //创建PCB
{
int i;
for (i = 1; i <= n; i++)//输入我们提供的进程信息
{
printf("\n%d:\n input the information of process\n input processID:", i);
scanf("%d", &pcb[i].name);
printf("input the arrivetime:");
scanf("%d", &pcb[i].arrivetime);
printf("input the servicetime:");
scanf("%d", &pcb[i].servicetime);
printf("input the priority:");
scanf("%d", &pcb[i].priority);
pcb[i].remain_time = pcb[i].servicetime; //初始时,剩余时间为服务时间
}
}
void layout(int n)
{
int ch = 0;
printf("\t\t************schedule algorithm************\n");
printf("\t\t1.FSFS\n");
printf("\t\t2.timesegment\n");
printf("\t\t3.priority\n");
printf("\t\t4.SJF\n");
printf(" choose the algorithm:\n");
scanf("%10d", &ch);
switch (ch)
{
case 1:
FCFS(n);
print_FCFS(n);
break;
case 2:
time_segment(n);
print_time(n);
break;
case 3:
Priority(n);
break;
case 4:
SJF(n);
break;
default:printf("enter error data!\n");
//P:int类型的变量,case后面不要加''
}
}
(一)先来先服务
先来先服务,也就是谁先来谁就先执行,即arrivetime越小执行的越早
预期结果:
代码实现:
void FCFS(int n) //先来先服务
{
int starttime;//系统开始工作的时间
printf("input the start time:\n");
scanf("%d", &starttime);
//我们虽然没有在pcd[0]中放我们的进程,但我们可以把他想象成一个需要服务时间为0的进程,有助于后面进程状态的计算
if (starttime >= pcb[0].arrivetime)//这种情况也就是,进程到达了,但系统还没开始工作
{ //所以完成时间是,系统开始工作的时间+进程需要接受服务的时间
pcb[0].finishtime = pcb[0].servicetime + starttime;
}
else
{ //这种就是正常情况了
pcb[0].finishtime = pcb[0].arrivetime + pcb[0].servicetime;
}
int i;
for (i = 1; i <= n; i++)
{
if (pcb[i - 1].finishtime > pcb[i].arrivetime) {
//这种情况是,虽然第i个进程已到达,但它的上一个进程还未结束,所以要等到上一进程结束它才能开始执行
pcb[i].finishtime = pcb[i - 1].finishtime + pcb[i].servicetime;
}
else {
pcb[i].finishtime = pcb[i].arrivetime + pcb[i].servicetime;
}
pcb[i].turntime = pcb[i].finishtime - pcb[i].arrivetime;//周转时间
pcb[i].weight_turntime = pcb[i].turntime / pcb[i].servicetime;//带权周转时间=周转时间/服务时间
}
}
void print_FCFS(int n)//输入结果
{
printf("process ID arrivetime servicetime finishtime turntime , averageturntime .\n");
int i;
for (i = 1; i <= n; i++)
{
printf("%d ,%d ,%d ,%d ,%d ,%d ", pcb[i].name, pcb[i].arrivetime, pcb[i].servicetime, pcb[i].finishtime, pcb[i].turntime, pcb[i].weight_turntime);
printf("\n");
}
}
使starttime = 0, 执行结果(与预期相符):
(二)时间片轮转调度算法
初始时按FCFS的方式排队,每个进程执行完一个时间片后,就移到队尾,等待下一次调度:
代码实现:
void time_segment(int n) //时间片轮转调度
{
int i, j;
int T; //时间片
int flag = 1; //就绪队列中是否还有进程
int time=pcb[1].arrivetime; //记录当前的时间
int sum = 0; //已经完成的进程数
//时间片轮转调度算法,初始时按FCFS的方式排队,所以按各进程的arrivetime进行升序排列
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
{
if (pcb[j].arrivetime < pcb[i].arrivetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
printf("input the slice time:\n");
scanf("%d", &T);//输入时间片大小
while (sum < n)//使用while循环遍历所有进程,直到所有进程都已完成。
{
flag = 0; //当前就绪队列中没有进程
int i;
for (i = 1; i <= n; i++)
{
if (pcb[i].sign == 1) {
continue; //如果进程已完成(`sign==1`),则跳过该进程
}else
{
//没有完成的进程需要的时间大于一个时间片
if (pcb[i].remain_time > T)
{
flag = 1;//将进程放入队列
time = time + T;//执行完一个时间片后,当前时间+T
pcb[i].remain_time = pcb[i].remain_time - T;
}else if (pcb[i].remain_time <= T)//没有完成的进程需要的时间小于或等于一个时间片
{
flag = 1; //加入就绪队列
time = time + pcb[i].remain_time;//time改为完成该进程后的时间
pcb[i].finishtime = time;
pcb[i].sign = 1;//将该进程的状态修改为“已完成”
pcb[i].remain_time = 0;
}
if (pcb[i].sign == 1) sum++;//如果完成了进程pcd[i],则将已完成进程数加1
}
}
if (flag == 0 && sum < n) // 还有没执行的进程,且没进入就就绪队列
{
int i;
for (i = 1; i <= n; i++){
if (pcb[i].sign == 0) {//找到未执行的进程
time = pcb[i].arrivetime;
break;
}
}
}
}//while
}
void print_time(int n)//输出结果
{
int i;
printf("\n processID servicetime finishtime\n"); //进程名 服务时间 完成时间
for (i = 1; i <= n; i++)
{
printf("%6d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].finishtime);
printf("\n");
}
}
执行结果:
(三)优先级调度算法(非抢占)
预期结果:
代码实现:
void Priority(int n)
{
int i, j;
int time = pcb[1].arrivetime;
//按各进程按arrivetime进行升序排列,最早到达的进程会直接占用CPU,不需要比较优先级
for (i = 1; i <= n; i++){
for (j = i + 1; j <= n; j++)
{
if (pcb[j].arrivetime < pcb[i].arrivetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
}
printf("\n processID servicetime priority finishtime \n");//进程名 服务时间 优先级 完成时间
//第一个到达的进程执行
if(i=1){//将i赋值为1
pcb[i].finishtime = pcb[i].arrivetime + pcb[i].servicetime;
time = pcb[i].arrivetime + pcb[i].servicetime;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);//输出第一个进程的信息
printf("\n");
}
//剩余进程按priority进行降序排列, 优先级最高的进程先执行
for (i = 2; i <= n; i++){
for (j = i + 1; j <= n; j++)
{
if (pcb[j].priority > pcb[i].priority)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
}
//输出信息
for (i = 2; i <= n; i++)
{
time = time + pcb[i].servicetime;
pcb[i].finishtime = time;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);
printf("\n");
}
}
执行结果:
(四)短作业优先调度算法(非抢占)
看了(三)中的优先级调度算法后,这个就简单了,就是把servicetime(服务时间),作为优先级
预期结果:
代码实现:
void SJF(int n) {
int i, j;
int time = pcb[1].arrivetime;
//按各进程的arrivetime进行升序排列,最早到达的进程先执行
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
{
if (pcb[j].arrivetime < pcb[i].arrivetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
printf("\n processID servicetime priority finishtime \n");//进程名 服务时间 优先级 完成时间
//按各进程的arrivetime进行升序排列,最早到达的进程会直接占用CPU,不需要比较优先级
if (i =1)
{
pcb[i].finishtime = pcb[i].arrivetime + pcb[i].servicetime;
time = pcb[i].arrivetime + pcb[i].servicetime;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);
printf("\n");
i++;
}
//按各进程的servicetime进行降序排列,优先级最高的进程先执行
for (i = 2; i <= n; i++)
for (j = i + 1; j <= n; j++)
{
if (pcb[j].servicetime < pcb[i].servicetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
for (i = 2; i <= n; i++)
{
time = time + pcb[i].servicetime;
pcb[i].finishtime = time;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);
printf("\n");
}
}
执行结果:
三、所有代码
#include<stdio.h>
#include<malloc.h>
#define max 50
struct PCB
{
int name;
int arrivetime; //到达时间
int servicetime; //服务时间
int starttime; //开始时间
int finishtime; //完成结束时间
int turntime; //周转时间
int weight_turntime; //带权周转时间
int sign; //标志进程是否完成
int remain_time; //剩余时间
int priority; //优先级
}pcb[max];
void init(int n);
void creat(int n);
void layout(int n);
void FCFS(int n);
void print_FCFS(int n);
void Priority(int n);
void SJF(int n);
void time_segment(int n);
void print_time(int n);
int main() {
int n;
printf("input the number of process\n");
scanf("%d", &n);
init(n);
creat(n);
layout(n);
return 0;
}
void init(int n) //初始化
{
int i;
for (i = 0; i <= n; i++)//元素均初始化为0
{
pcb[i].arrivetime = 0;
pcb[i].servicetime = 0;
pcb[i].starttime = 0;
pcb[i].finishtime = 0;
pcb[i].turntime = 0;
pcb[i].weight_turntime = 0;
pcb[i].remain_time = 0;
pcb[i].sign = 0;
pcb[i].priority = 0;
}
}
void creat(int n) //创建PCB
{
int i;
for (i = 1; i <= n; i++)//输入我们提供的进程信息
{
printf("\n%d:\n input the information of process\n input processID:", i);
scanf("%d", &pcb[i].name);
printf("input the arrivetime:");
scanf("%d", &pcb[i].arrivetime);
printf("input the servicetime:");
scanf("%d", &pcb[i].servicetime);
printf("input the priority:");
scanf("%d", &pcb[i].priority);
pcb[i].remain_time = pcb[i].servicetime; //初始化剩余时间为服务时间
}
}
void layout(int n)
{
int ch = 0;
printf("\t\t************schedule algorithm************\n");
printf("\t\t1.FSFS\n");
printf("\t\t2.timesegment\n");
printf("\t\t3.priority\n");
printf("\t\t4.SJF\n");
printf(" choose the algorithm:\n");
scanf("%10d", &ch);
switch (ch)
{
case 1:
FCFS(n);
print_FCFS(n);
break;
case 2:
time_segment(n);
print_time(n);
break;
case 3:
Priority(n);
break;
case 4:
SJF(n);
break;
default:printf("enter error data!\n");
//P:int类型的变量,case后面不要加''
}
}
void SJF(int n) {
int i, j;
int time = pcb[1].arrivetime;
//按各进程的arrivetime进行升序排列,最早到达的进程先执行
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
{
if (pcb[j].arrivetime < pcb[i].arrivetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
printf("\n processID servicetime priority finishtime \n");//进程名 服务时间 优先级 完成时间
//按各进程的arrivetime进行升序排列,最早到达的进程会直接占用CPU,不需要比较优先级
if (i =1)
{
pcb[i].finishtime = pcb[i].arrivetime + pcb[i].servicetime;
time = pcb[i].arrivetime + pcb[i].servicetime;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);
printf("\n");
i++;
}
//按各进程的servicetime进行降序排列,优先级最高的进程先执行
for (i = 2; i <= n; i++)
for (j = i + 1; j <= n; j++)
{
if (pcb[j].servicetime < pcb[i].servicetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
for (i = 2; i <= n; i++)
{
time = time + pcb[i].servicetime;
pcb[i].finishtime = time;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);
printf("\n");
}
}
void FCFS(int n) //先来先服务
{
int starttime;//系统开始工作的时间
printf("input the start time:\n");
scanf("%d", &starttime);
//我们虽然没有在pcd[0]中放我们的进程,但我们可以把他想象成一个需要服务时间为0的进程,有助于后面进程状态的计算
if (starttime >= pcb[0].arrivetime)//这种情况也就是,进程到达了,但系统还没开始工作
{ //所以完成时间是,系统开始工作的时间+进程需要接受服务的时间
pcb[0].finishtime = pcb[0].servicetime + starttime;
}
else
{ //这种就是正常情况了
pcb[0].finishtime = pcb[0].arrivetime + pcb[0].servicetime;
}
int i;
for (i = 1; i <= n; i++)
{
if (pcb[i - 1].finishtime > pcb[i].arrivetime) {
//这种情况是,虽然第i个进程已到达,但它的上一个进程还未结束,所以要等到上一进程结束它才能开始执行
pcb[i].finishtime = pcb[i - 1].finishtime + pcb[i].servicetime;
}
else {
pcb[i].finishtime = pcb[i].arrivetime + pcb[i].servicetime;
}
pcb[i].turntime = pcb[i].finishtime - pcb[i].arrivetime;//周转时间
pcb[i].weight_turntime = pcb[i].turntime / pcb[i].servicetime;//带权周转时间=周转时间/服务时间
}
}
void print_FCFS(int n)//输入结果
{
printf("process ID arrivetime servicetime finishtime turntime , averageturntime .\n");
int i;
for (i = 1; i <= n; i++)
{
printf("%d ,%d ,%d ,%d ,%d ,%d ", pcb[i].name, pcb[i].arrivetime, pcb[i].servicetime, pcb[i].finishtime, pcb[i].turntime, pcb[i].weight_turntime);
printf("\n");
}
}
void Priority(int n)
{
int i, j;
int time = pcb[1].arrivetime;
//按各进程按arrivetime进行升序排列,最早到达的进程会直接占用CPU,不需要比较优先级
for (i = 1; i <= n; i++){
for (j = i + 1; j <= n; j++)
{
if (pcb[j].arrivetime < pcb[i].arrivetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
}
printf("\n processID servicetime priority finishtime \n");//进程名 服务时间 优先级 完成时间
//第一个到达的进程执行
if(i=1){//将i赋值为1
pcb[i].finishtime = pcb[i].arrivetime + pcb[i].servicetime;
time = pcb[i].arrivetime + pcb[i].servicetime;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);//输出第一个进程的信息
printf("\n");
}
//剩余进程按priority进行降序排列, 优先级最高的进程先执行
for (i = 2; i <= n; i++){
for (j = i + 1; j <= n; j++)
{
if (pcb[j].priority > pcb[i].priority)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
}
//输出信息
for (i = 2; i <= n; i++)
{
time = time + pcb[i].servicetime;
pcb[i].finishtime = time;
printf("%6d%10d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].priority, pcb[i].finishtime);
printf("\n");
}
}
void time_segment(int n) //时间片轮转调度
{
int i, j;
int T; //时间片
int flag = 1; //就绪队列中是否还有进程
int time=pcb[0].arrivetime; //记录当前的时间
int sum = 0; //已经完成的进程数
//时间片轮转调度算法,初始时按FCFS的方式排队,所以按各进程的arrivetime进行升序排列
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++)
{
if (pcb[j].arrivetime < pcb[i].arrivetime)
{
pcb[0] = pcb[j];
pcb[j] = pcb[i];
pcb[i] = pcb[0];
}
}
printf("input the slice time:\n");
scanf("%d", &T);//输入时间片大小
while (sum < n)//使用while循环遍历所有进程,直到所有进程都已完成。
{
flag = 0; //当前就绪队列中没有进程
int i;
for (i = 1; i <= n; i++)
{
if (pcb[i].sign == 1) {
continue; //如果进程已完成(`sign==1`),则跳过该进程
}else
{
//没有完成的进程需要的时间大于一个时间片
if (pcb[i].remain_time > T)
{
flag = 1;//将进程放入队列
time = time + T;//执行完一个时间片后,当前时间+T
pcb[i].remain_time = pcb[i].remain_time - T;
}else if (pcb[i].remain_time <= T)//没有完成的进程需要的时间小于或等于一个时间片
{
flag = 1; //加入就绪队列
time = time + pcb[i].remain_time;//time改为完成该进程后的时间
pcb[i].finishtime = time;
pcb[i].sign = 1;//将该进程的状态修改为“已完成”
pcb[i].remain_time = 0;
}
if (pcb[i].sign == 1) sum++;//如果完成了进程pcd[i],则将已完成进程数加1
}
}
if (flag == 0 && sum < n) // 还有没执行的进程,且没进入就就绪队列
{
int i;
for (i = 1; i <= n; i++){
if (pcb[i].sign == 0) {//找到未执行的进程
time = pcb[i].arrivetime;
break;
}
}
}
}//while
}
void print_time(int n)//输出结果
{
int i;
printf("\n processID servicetime finishtime\n"); //进程名 服务时间 完成时间
for (i = 1; i <= n; i++)
{
printf("%6d%10d%10d", pcb[i].name, pcb[i].servicetime, pcb[i].finishtime);
printf("\n");
}
}