进程管理是操作系统中的重要功能,用来创建进程、撤消进程、实现进程状态转换,它提供了在可运行的进程之间复用CPU的方法。在进程管理中,进程调度是核心,因为在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态,当就绪进程个数大于处理器数目时,就必须依照某种策略决定哪些进程优先占用处理器。本设计模拟在单处理器情况下的进程调度,目的是加深对进程调度工作的理解,掌握不同调度算法的优缺点。
设计程序模拟单处理机系统中的进程调度算法,在短作业优先调度算法、时间片轮转调度、最高优先级优先算法三种算法中选择两种实现。
每个进程由一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等。
进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪W(Wait)、运行R(Run)或完成F(Finish)3中状态之一。
在非抢占式的调度算法中,最先到达的进程最先运行,在进程进行的时候,到达的进程之间就要进行运行时间的比较,运行时间依次从少到多排列,最短运行时间的先运行,每次只能运行一个进程,每当进程运行时,每次到达的新进程都跟等待状态的进程进行比较,进程根据运行时间排序,直到所有进程都到达,所有的进程都运行完结束就打印结果。
在执行主函数的时候,选择短作业优先调度算法或者最高优先级优先算法,利用if语句来判断执行什么函数。
调用void input(PCB *a,int n)函数,从键盘输入进程的信息,然后调用void qiushu(PCB *a,int n)函数,在qiushu函数中,依次调用void compare(PCB *a,int n),void run(PCB *a,int n) ,void output(PCB *a,int n) 。
在void compare(PCB *a,int n)中,
①先利用冒泡排序按照提交时间的早晚排序得到a[],先执行最先到达的进程a[0];
②在进程执行完之前比较已经到达的进程的运行时间,依次按照运行时间的多少根据从小到大排列得到序列,a[0]完成后执行当前最小运行时间的进程a[1];
③再执行②,直到所有进程执行完。
在void run(PCB *a,int n)中,
求出运行进程的开始时间,完成时间,周转时间,带权周转时间。
第一个进程的开始时间为它的提交时间,其他的进程都为上一个进程的完成时间;
完成时间=开始时间+运行时间;
周转时间=完成时间-提交时间;
带权周转时间=周转时间/运行时间。
在void output(PCB *a,int n)中,
输出进程的运行顺序以及进程运行的具体信息。
建立结构体来记录进程的基本信息。
struct PCB{ //定义结构体
int jcxh; //进程号
double tjtime; //提交时间
double yxtime; //运行时间
double startime; //开始时间
double finishtime; //完成时间
double zztime; //周转时间
double dqzztime; //带权周转时间
int prior; //优先级数
double RunTime; //已占用cpu时间
char state; //进程状态
struct PCB* next; //创建指针
};
PCB a[10]; 最高只能有十个进程
struct PCB{ //定义结构体
int jcxh; //进程号
double tjtime; //提交时间
double yxtime; //运行时间
double startime; //开始时间
double finishtime; //完成时间
double zztime; //周转时间
double dqzztime; //带权周转时间
int prior; //优先级数
double RunTime; //已占用cpu时间
char state; //进程状态
struct PCB* next; //创建指针
};
PCB a[10]; //最多十个进程数
//排序
void compare(PCB *a,int n)
{
int i,j,m;
for(i=0;i for(j=i+1;j<=n-1;j++) if(a[i].tjtime>a[j].tjtime) { PCB b; b=a[i]; a[i]=a[j]; a[j]=b; } for(m=0;m { if(m==0) a[m].finishtime=a[m].tjtime+a[m].yxtime; else a[m].finishtime=a[m-1].finishtime+a[m].yxtime; int l,q=0; for(l=m+1;l<=n-1;l++) { if(a[l].tjtime<=a[m].finishtime) q++; } double min=a[m+1].yxtime; int next=m+1;//m+1=n for(int k=m+2;k<=m+q;k++) { if(a[k].yxtime { min=a[k].yxtime; next=k;} } PCB c; c=a[m+1]; a[m+1]=a[next]; a[next]=c; } } me=a[i].zztime/a[i].yxtime;//求出带权周转时间 } } void output(PCB *a,int n) { int i; printf("使用短作业算法后进程的运行顺序:"); for(i=0;i {if(i==0)printf("%d",a[i].jcxh); else printf("--->%d",a[i].jcxh); } printf("\n"); printf("进程名 提交时间 运行时间 开始时间 完成时间 周转时间 带权周转时间\n"); for(i=0;i { printf(" %d %.2lf %.2lf %.2lf %.2lf\t%.2lf\t %.2lf\n",a[i].jcxh,a[i].tjtime,a[i].yxtime,a[i].startime,a[i].finishtime,a[i].zztime,a[i].dqzztime); } } 在短作业优先调度算法中,实现并不难。从键盘输入进程信息,再进而比较每个的提交时间,先执行最先来到的进程,再根据运行时间的大小,选择短作业的优先进入cpu。 7.心得体会