开始 Y 空闲进程控制 块队列为空? N 取空闲进程控制块队列的第一个i=pfree 进程创建失败 pfree后移: pfree=pcbarea[pfree].next 填写该进程控制块的内容: pcbarea[i].name=name; pcbarea[i].status=aready; 初始化进程控制块内的现场信息; Y 就绪队列为空? N 挂入就绪队列: pcbarea[ready.tail].next=i; ready.tail=i; pcbarea[ready.tail].next=-1; 挂入就绪队列: ready.head=i; ready.tail=i; pcbarea[ready.tail].next=-1; 结束 图1 进程创建流程图
多道程序设计的系统中,处于就绪状态的进程往往有多个,它们都要求占用处理器,可是单处理器系统的处理器只有一个,进程调度就是解决这个处理器竞争问题的。进程调度的任务就是按照某种算法从就绪进程队列中选择一个进程,让它占有处理器。因此,进程调度程序就应该包括两部分,一部分是在进程就绪队列中选择一个进程,并将其进程控制块从进程就绪队列中摘下来,另一部分工作就是分配处理器给选中的进程,也就是将指向正在运行进程的进程控制块指针指向该进程的进程控制块,并将该进程的进程控制块信息写入处理器的各个寄存器中。
实验参考程序中采用时间片轮转调度算法,这种算法让就绪进程按就绪的先后次序排成队列,每次总是选择就绪队列中的第一个进程占有处理器,但是规定只能使用一个“时间片”。
采用时间片轮转调度算法的进程调度流程图如图2所示。
开始 Y 就绪队列为空? N 就绪队列头指针赋给i: i= ready.head 就绪队列头指针后移: ready.head =pcbarea[ready.head].next 无进程可以调度 就绪队列为空? Y 就绪队列队尾指针置为空: ready.tail=-1 N 修改进程控制块状态: pcbarea[i].status=running 设置相对时钟寄存器: TIME=时间片 恢复该进程现场信息: AX=ax;BX=bx;CX=cx;DX=dx; PC=pc;PSW=psw; 修改指向运行进程的指针: run=i 图2 进程调度流程图
完成上述功能后,编写主函数进行测试:首先建立一个就绪队列,手工输入信息建立几个进程;然后进行进程调度;最后将指向正在运行进程的指针指向的进程控制块内容输出,察看结果。
2)参考程序
#include “stdio.h”
#define running 1 // 用running表示进程处于运行态 #define aready 2 // 用aready表示进程处于就绪态 #define blocking 3 // 用blocking表示进程处于阻塞态 #define sometime 5 // 用sometime表示时间片大小 #define n 10 //假定系统允许进程个数为n struct {
int name; int status; int ax,bx,cx,dx ; int pc ; int psw; int next; }pcbarea[n]; int PSW, AX,BX,CX,DX , PC ,TIME ; int run; struct {
int head; int tail;
}ready; int pfree;
scheduling( ) {
int i;
if (ready.head==-1) {
printf(“无就绪进程\\n”); return; }
i=ready.head; ready.head=pcbarea[ready.head].next; if(ready.head==-1) ready.tail=-1; pcbarea[i].status=running; TIME=sometime; //恢复该进程现场信息 AX=pcbarea[run].ax; BX=pcbarea[run].bx; CX=pcbarea[run].cx; DX=pcbarea[run].dx; PC=pcbarea[run].pc;
//进程标识符 //进程状态
//进程现场信息,通用寄存器内容 //进程现场信息,程序计数器内容 //进程现场信息,程序状态字内容 //下一个进程控制块的位置 //模拟进程控制块区域的数组 //模拟寄存器
//定义指向正在运行进程的进程控制块的指针 //定义就绪队列的头指针head和尾指针tail //定义指向空闲进程控制块队列的指针 //进程调度函数 //空闲进程控制块队列为空,退出 //就绪队列头指针赋给i //就绪队列头指针后移
//就绪队列为空,修正尾指针ready.tail //修改进程控制块状态 //设置相对时钟寄存器 PSW=pcbarea[run].psw; run=i;
}//进程调度函数结束
create(int x) //进程创建函数 {
int i;
if(pfree==-1) //空闲进程控制块队列为空 {
printf(“无空闲进程控制块,进程创建失败\\n”); return; }
i=pfree; //取空闲进程控制块队列的第一个 pfree=pcbarea[pfree].next; // pfree后移 //填写该进程控制块的内容 pcbarea[i].name=x;
pcbarea[i].status=aready; pcbarea[i].ax=x; pcbarea[i].bx=x; pcbarea[i].cx=x; pcbarea[i].dx=x; pcbarea[i].pc=x; pcbarea[i].psw=x;
if (ready.head!=-1) //就绪队列不为空时,挂入就绪队列的方式 {
pcbarea[ready.tail].next=i; ready.tail=i;
pcbarea[ready.tail].next=-1; }
else //就绪队列为空时,挂入就绪队列的方式 {
ready.head=i; ready.tail=i;
pcbarea[ready.tail].next=-1; }
}//进程创建函数结束
main()
{ //系统初始化 int num,i,j;
run=ready.head=ready.tail =-1; pfree=0;
for(j=0;j pcbarea[j].next=j+1; pcbarea[n-1].next=-1; printf(“输入进程编号(避免编号冲突,以负数输入结束,最多可以创建10个进程):\\n”); scanf(“%d”,&num); while(num>=0) { create(num) ; scanf(“%d”,&num) ; } scheduling(); //进程调度 if(run!=-1) { printf(“进程标识符 进程状态 寄存器内容:ax bx cx dx pc psw:\\n”); printf(“?d======\\n”, pcbarea[run].name, pcbarea[run].status, pcbarea[run].ax, pcbarea[run].bx, pcbarea[run].cx, pcbarea[run].dx, pcbarea[run].pc, pcbarea[run].psw); } }//main()结束