一、 实验目的
用C语言模拟进程调度程序,以加深对进程的概念及进程调度算法的理解。
二、 实验内容及要求
设计一个有 N个进程并发执行的进程调度模拟程序。
进程调度算法:
(1) 先来先服务调度算法,即按作业到达的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。
(2) 优先级调度算法,为每个作业设置一个优先级,调度之前先比较各作业的优先级,优先数高者优先调度,若优先级相同则用先来先服务算法。
1)每个进程有一个进程控制块(PCB)表示。进程控制块包含如下信息:进程名、优先级、到达时间、需要运行时间、已用CPU时间、进程状态等等。
2)进程的优先级及需要的运行时间可以事先人为地指定,进程的运行时间以时间片为单位进行计算。
3)每个进程的状态可以是就绪 r(ready)、运行R(Running)、或完成F(Finished)三种状态之一。
4)就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
5)如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待调度。
6)每进行一次调度程序都打印一次运行进程、就绪队列中各个进程的 PCB,以便进行检查。
7)重复以上过程,直到所要进程都完成为止。
三、 实验方法及结果测试
(1)先来先服务调度算法:
#include<stdio.h>
#include<stdlib.h>
typedef struct PCB {
char name[30];//进程名称
float arriveTime;//到达时间
float serveTime;//服务时间
float finishTime;//完成时间
} FCFS;
struct PCB a[100];
struct PCB *sortArriveTime(struct PCB a[],int n);//到达时间冒泡排序
void Fcfs(struct PCB a[],int n);//FCFS算法
//按到达时间进行冒泡排序
struct PCB *sortArriveTime(struct PCB a[],int n) {
int i,j;
struct PCB t;
int flag;
for(i=1; i<n; i++) {
flag=0;
for(j=0; j<n-i; j++) {
if(a[j].arriveTime>a[j+1].arriveTime) { //将到达时间短的交换到前边
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
flag=1;//交换
}
}
if(flag=0) { //如果一趟排序中没发生任何交换,则排序结束
break;
}
}
return a;//返回排序后进程数组
}
//先来先服务算法
void Fcfs(struct PCB a[],int n) {
int i;
a[0].finishTime=a[0].arriveTime+a[0].serveTime;//完成时间=到达时间+服务时间
for(i=1; i<n; i++) {
if(a[i].arriveTime<a[i-1].finishTime) { //当前到达时间在上一个作业结束时间之前
a[i].finishTime=a[i-1].finishTime+a[i].serveTime;//完成时间=上一个完成时间+服务时间
} else {
a[i].finishTime=a[i].arriveTime+a[i].serveTime;
}
}
printf("进程名称\t到达时间\t服务时间\t完成时间\t\n");
for(i=0; i<n; i++) {
printf(" %s\t",a[i].name);
printf("\t%f",a[i].arriveTime);
printf("\t%f",a[i].serveTime);
printf("\t%f",a[i].finishTime);
printf("\n");
}
}
main() {
int n,i;
printf("\n *************进程调度算法(先来先服务算法)************\n\n");
printf("请输入进程数目:");
scanf("%d",&n);
printf("\n");
for(i=0; i<n; i++) {
printf("第%d个进程的名称:",i+1);
scanf("%s",&a[i].name);
printf("第%d个进程的到达时间:",i+1);
scanf("%f",&a[i].arriveTime);
printf("第%d个进程的服务时间:",i+1);
scanf("%f",&a[i].serveTime);
printf("\n");
}
sortArriveTime(a,n);//冒泡排序
Fcfs(a,n);//先来先服务算法
}
测试结果:
(2)优先级调度算法:
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
/*定义进程结构体*/
typedef struct pcb {
char name[30];//进程名称
int priority ;//进程优先数
int serveTime;//进程到达时间
int cpuTime;//进程占用CPU时间
char state;//进程状态
} PCB;
Input(PCB p[MAX],int n) {
int i;
for(i=0; i<n; i++) {
printf("第%d个进程的名称:",i+1);
scanf("%s",&p[i].name);
printf("第%d个进程的优先数:",i+1);
scanf("%d",&p[i].priority);
printf("第%d个进程的服务时间:",i+1);
scanf("%d",&p[i].serveTime);
p[i].state=‘W‘;
p[i].cpuTime=0;
printf("\n");
}
}
Output(PCB p[MAX],int n) {
int i;
printf("进程名称\t优先级数\t服务时间\t当前时间\t进程状态\n");
for(i=0; i<n; i++) {
printf(" %s\t",p[i].name);
printf("\t%d\t",p[i].priority);
printf("\t%d\t",p[i].serveTime);
printf("\t%d\t",p[i].cpuTime);
printf("\t%c\t",p[i].state);
printf("\n");
}
}
PrioritySort(PCB p[MAX],int n) {
int m=0,i=0,j ;
PCB temp;
m = n;
for(i = 1 ; i < n ; i++) {
m = m - 1 ;
for(j = 0 ; j < m ; j ++) {
if(p[j].priority < p[j+1].priority) {
temp = p[j];
p[j] = p[j+1];
p[j+1] = temp ;
}
}
}
}
Run(PCB p[MAX] , int n) {
int i ,j ;
int m=0;
for(i = 0 ; i < n ; i ++) {
m = p[i].serveTime+m;
}
for(i = 0 ; i < n ; i ++) {
for(j = 0 ; j < m ; j ++) {
printf("请按回车键继续运行......!\n");
getchar();
p[i].priority--;
p[i].cpuTime++;
p[i].serveTime--;
p[i].state=‘R‘;
PrioritySort(p,n);
Output(p,n);
if(p[i].serveTime!=0) {
p[i].state=‘R‘;
} else {
p[i].state=‘F‘;
printf("********第%d个进程的运行完成!********\n",i+1);
break;
}
}
}
}
End(PCB p[MAX] , int n) {
int i ,j ;
for(i = 0 ; i < n ; i ++) {
if(p[i].serveTime==0){
p[i].state=‘F‘;
}
}
Output(p,n);
printf("********进程调度结束!********\n",i+1);
}
main() {
PCB p[MAX];
int n,i;
printf("\n *************进程调度算法(优先级调度算法)************\n\n");
printf("请输入进程数目:");
scanf("%d",&n);
printf("\n");
Input(p,n);
PrioritySort(p,n);
Output(p,n);
getchar();
Run(p,n);
End(p,n);
}
测试结果:
四、 实验总结
1、总的来说,进程调度理解起来并不难,反而挺简单,但用程序语言模拟其过程就有点困难了;
2、虽说这两个进程调度算法可以算是简单模拟出效果,但其中还有很多需要改进。