赞
踩
用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解
综合性实验。综合高级语言编程、进程调度模型、进程调度算法及数据结构等多方面的知识
例题: 设计一个有 N个进程共行的进程调度程序
进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。
每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输
入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。
调度算法的流程图如下 :
- #include "stdio.h"
- #include <stdlib.h>
- #include <conio.h>
- #define getpch(type) (type*)malloc(sizeof(type)) //分配type类型大小的空间
- #define NULL 0
- struct pcb { /* 定义进程控制块PCB */
- char name[10]; //进程名
- char state; //进程状态
- int super; //进程优先级
- int ntime; //进程总共需要运行的时间
- int rtime; //进程已经运行的时间
- struct pcb* link; //指向后继节点的指针
- }*ready=NULL,*p; //ready指针永远指向队列的第一个进程
- typedef struct pcb PCB;
-
- sort() /* 建立对进程进行优先级排列函数*/
- {
- PCB *first, *second; // 指针second指向队列中当前处理的进程,指针first指向second的前驱节点,指针p指向准备插入队列的进程;
- int insert=0; //判断是否
- if((ready==NULL)||((p->super)>(ready->super))) /*优先级最大者,插入队首*/
- {
- p->link=ready; //p指向的进程优先级最高,要成为队列中新的队首节点,即ready要修改指向p;
- ready=p;
- }
- else /* 如果队列有至少一个进程,则进程比较优先级,插入适当的位置中*/
- {
- first=ready; // first指向队首节点;
- second=first->link; // second指向第2个节点;
- while(second!=NULL) //如果有第2个节点,即队列至少有2个节点;
- {
- if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/
- { /*插入到当前进程前面*/ //p指向的进程要插入到first和sencond之间,修改指针;
- p->link=second;
- first->link=p;
- second=NULL; //找到了进程插入的位置,把second设为NULL,退出while循环;
- insert=1; //insert为1表示p指向的进程插入在两个进程之间;
- }
- else /* 插入进程优先数最低,则插入到队尾*/
- {
- first=first->link; // 此时first指向原队列最后一个进程;
- second=second->link; //此时second为NULL;
- }
- }
- if(insert==0) first->link=p; // insert为0表示p指向的进程插入到队尾
- }
- }
-
- input() /* 建立进程控制块函数*/
- {
- int i,num;
- //clrscr(); /*清屏*/
- printf("\n 请输入进程号?"); //输入需要调度的进程数量
- scanf("%d",&num);
- for(i=0;i<num;i++) //依次输入每个进程控制块的信息;
- {
- printf("\n 进程号No.%d:\n",i);
- p=getpch(PCB);
- printf("\n 输入进程名:");
- scanf("%s",p->name);
- printf("\n 输入进程优先数:");
- scanf("%d",&p->super);
- printf("\n 输入进程运行时间:");
- scanf("%d",&p->ntime);
- printf("\n");
- p->rtime=0;p->state='w';
- p->link=NULL;
- sort(); /* 调用sort函数*/ //把新创建的进程按优先级插入到队列中;
- }
- }
- int space() //获取当前队列的长度,即需要调度的进程个数;
- {
- int l=0; PCB* pr=ready; //pr指向队列第一个进程,即对首进程
- while(pr!=NULL) //依次遍历整个队列,计算长度
- {
- l++; //是字符l,不是数字1,代表队列长度;
- pr=pr->link;
- }
- return(l);
- }
- disp(PCB * pr) /*建立进程显示函数,用于显示当前进程的信息*/
- {
- printf("\n qname \t state \t super \t ndtime \t runtime \n");
- printf("|%s\t",pr->name);
- printf("|%c\t",pr->state);
- printf("|%d\t",pr->super);
- printf("|%d\t",pr->ntime);
- printf("|%d\t",pr->rtime);
- printf("\n");
- }
- check() /* 建立进程查看函数 */ //查看当前队列中每个进程信息
- {
- PCB* pr;
- printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/
- disp(p);
- pr=ready; // pr指向队列对首进程
- printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/
- while(pr!=NULL) //循环遍历队列中每个进程
- {
- disp(pr);
- pr=pr->link;
- }
- }
- destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/
- {
- printf("\n 进程 [%s] 已完成.\n",p->name);
- free(p);
- }
- running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/
- {
- (p->rtime)++; //p指向当前运行进程,即从原队列中的对首进程,运行次数加1,rtime表示已运行的时间片;
- if(p->rtime==p->ntime) //如果进程需要运行总时间ntime和已运行时间rtime相等,表示该进程已经运行完毕,需要撤销;
- destroy(); /* 调用destroy函数*/
- else //如果该进程没有运行完毕,则使它的优先级减1,状态变为就绪,重新按优先级顺序插入到队列中;
- {
- (p->super)--;
- p->state='w';
- sort(); /*调用sort函数*/
- }
- }
- main() /*主函数*/
- {
- int len,h=0; //len:队列进程的个数;h:进程调度的时间片次数
- char ch; // 获取getchar()函数的字符
- input(); //输入要处理进程控制块信息
- len=space(); //当前进程队列的长度,即要处理的进程数量
- while((len!=0)&&(ready!=NULL)) //若队列不为空,即还有进程需要处理;
- {
- ch=getchar(); //从键盘获取字符
- h++; // h:进程执行的时间片次数序号
- printf("\n The execute number:%d \n",h); //
- p=ready; // ready永远指向队列的对首进程,p此时也指向队列的对首进程,但该对首进程需要出队列以便运行,;
- ready=p->link; //原队列的第2个进程成为新的对首进程
- p->link=NULL; //原对首进程出队列后,没有后继;
- p->state='R'; //原对首进程出队列后状态变为执行;
- check(); //查看当前队列中所有进程的信息,即原对首进程出队列后
- running();//原对首进程运行
- printf("\n 按任一键继续......");
- ch=getchar();//从键盘获取字符
- }
- printf("\n\n 进程已经完成.\n");
- ch=getchar();//从键盘获取字符
- }
-
通过本次实验,进程动态调度的过程与人工分析的结果一致,基本达到预期的目标。通过用户自己定义进程号、进程名、进程优先数、进程运行时间。优先数高的进程先进入运行状态,其他进程则为就绪状态。若优先数高的进程运行一个时间片后仍需运行,则进入就绪状态,该进程优先数-1。若进程运行一个时间片后,已经达成所需要的运行时间,则该进程完成,进入完成状态。如果就绪队列里存有多个优先数相同的进程,则根据进程号先来先得的原则运行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。