终于弄好了课程设计,不过不是自己做的
二: 进程调度模拟程序
设计要求:
编写一程序,可以创建若干个虚拟进程,并对若干个虚拟进程进行调度,调度策略为时间片轮转。
虚拟程序的描述:
虚拟指令的格式: 操作命令 操作时间
其中,操作命令有以下几种:
l C : 表示在CPU上计算
l I :表示输入
l O:表示输出
l W:表示等待
l H:表示进程结束
操作时间代表该操作命令要执行多长时间
假设I/O设备的数量没有限制
I、O、W三条指令实际上是不占用CPU的,执行这三条指令就应将进程放入对应的等待队列(Input等待队列、Output等待队列、Wait等待队列)
例有一虚拟程序p1.prc描述如下:
c 30
o 12
c 9
i 14
h 0
该虚拟程序表示的含义是:先在CPU上计算30秒,再在输出设备上输出12秒,计算9 秒,在输入设备上输入14秒,程序结束。
实验方法:
先用文本编辑器写三个虚拟程序,可以分别命名为p1.prc p2.prc p3.prc。然后编一进程调度程序,将这三个虚拟程序创建成进程,并按各虚拟进程的指令要求执行和调度。用一个文本文件, 里面只能放一个整数,表示一个时间因子,用于调节设计程序OS.EXE的执行速度。
运行结果要求:
要求在每个线程创建、占用处理机、开始输出、开始输入和结束操作时分别显示一行提示信息,以确定所有处理都遵守相应的进程调度规则。
要求:
1. 设计的分析,解决方案
2. 进程的创建要创建进程控制块(可参考UINX的进程控制块的设计,要求有进程的必要信息)
3. 要有运行队列、就绪队列、Input等待队列、Output等待队列、Wait等待队列
4. 要有进程切换时的上下文转换过程
5. 要动态显示每个进程的当前状态及指令执行情况,动态显示每个队列的当前状态
6. 画出程序的基本结构框图和流程图
7. 对程序的每一部分要有详细的设计分析说明,说明设计实现所用的原理,采用的数据结构
8. 进程的各个操作函数的详细说明(如创建进程,销毁进程等)
9. 源代码格式规范,注释不少于三分之一
10. 对运行的结果要有结果的分析,
11. 设计中遇到的问题,设计的心得体会
12. 参考资料
13. 开发工具不限
系统流程图:
1.3 个作业
2. 按照时间片轮转法实现进程调度
3.五个公用队列
执行队列 |
时间片 |
就绪等待队列 |
CPU |
输入等待队列 |
H
结束 |
输出等待队列 |
阻塞等待队列 |
源程序
#define NULL 0
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
//定义一个pcb的结构体
FILE *GroupFile[10];
typedef struct index{
char name; //指令
int time; //指令执行时间
}index;
struct pcb {
char filename[10]; //进程名
int id; //作业编号
int exetoIndex; //当前正在执行指令
char status; //当前状态
int wtime; //等待时间
};
struct pcb jobpcb[100]; //pcb表
typedef struct job{
index idx[100]; //指令集
int pcbnum; //pcb编号 对应
}job;
job jobtab[100]; //作业表
char jobp[3][50]; //作业
//队列
struct Qnode
{
int pcbnum[100]; //pcb编号
int head,tail;
};
struct Qnode Queue[5]; //5个队列 0E 1R 2I 3O 4W
void initqueue(struct Qnode *l);
//延迟
void delay( ){
long begin,end;
time(&begin);
do {
time(&end);
} while((end-begin)<=1);
}
//字符转化为数值
int change(char *m){
int i,j=0;
int len=strlen(m);
for(i=0;i<len;i++)
j=j*10+m[i]-'0';
return j;
}
//申请 pcb
int AllocPCB(){
int i;
for(i=0;i<3;i++)
if(jobpcb[i].id ==-1) break;
if(i<3)
return i;
return -1;
}
//申请job
int AllocJob(){
int i;
for(i=0;i<3;i++)
if(jobtab[i].pcbnum == -1) break;
if(i<3)
return i;
return -1;
}
//显示指令
void displayIndex(){
int i,j;
for(i=0;i<3;i++){
printf(" Job % d /n",i+1);
for(j=0;j<10;j++)
printf(" %d %c % d /n",j+1, jobtab[i].idx[j].name,jobtab[i].idx[j].time);
}
}
//创建进程程序
int creatpcbline(){
char line[10];
int i,ll,jnum, pnum, ln=0, bpos, pos=0;
char buff[50];
char name [20];
char ch;
for(i=0;i<3;i++){
ln=0;
jnum=AllocJob();
if(jnum == -1) return 0;
pnum=AllocPCB();
if(pnum == -1) return 0;
jobtab[jnum].pcbnum=pnum;
strcpy(jobpcb[pnum].filename," ");
jobpcb[pnum].status='r';
jobpcb[pnum].exetoIndex=0;
jobpcb[pnum].id=jnum;
jobpcb[pnum].wtime=0;
int ln=strlen(jobp[i]);
pos=0;
while(pos<len){
while(jobp[i][pos]==' ') pos++;
jobtab[jnum].idx[ln].name=jobp[i][pos++];///
while(jobp[i][pos]==' ') pos++;
bpos=0;
while(jobp[i][pos]!=' ')
buff[bpos++]=jobp[i][pos++];
buff[bpos]='/0';
jobtab[jnum].idx[ln].time=change(buff);/
if(pos<len) {pos++;ln++;
}
}
}
displayIndex();
}
/*初始化队列
void initqueue(struct Qnode *l){
l->head=0;
l->tail=0;
}
//插进入队列/
void insertqueue(struct Qnode *l,int pcbnum){
l->pcbnum[l->tail++]=pcbnum;
}
//队列是否为空
int EmptyQueue( struct Qnode l){
if(l.head==l.tail) return 1;
return 0;
}
//删除队列
void outqueue(struct Qnode *l,int *pcbnum)
{
if (l->head>=l->tail ) *pcbnum=-1;
else
*pcbnum=l->pcbnum[l->head++];
}
//显示作业
void display(){
int i,j;
for(i=0;i<5;i++){
printf(" 队列 %d ",i);
for(j=Queue[i].head;j<Queue[i].tail;j++)
printf("pcb 编号 %d /n/n ",Queue[i].pcbnum[j]);
}
}
//作业入队列
void JobEnQueueInit( int * total){
int i,num ,Index=0;
char cmd;
for( i=0;i<3;i++){
if(jobpcb[i].id>=0){
cmd=jobtab[ jobpcb[i].id ].idx[ Index ].name;
switch(cmd){
case 'c': insertqueue(&Queue[1],i); jobpcb[i].status='r'; break;
case 'i': insertqueue(& Queue[2],i);jobpcb[i].status='i'; break;
case 'o': insertqueue(& Queue[3],i);jobpcb[i].status='o'; break;
case 'w': insertqueue(& Queue[4],i);jobpcb[i].status='w'; break;
case 'h': jobpcb[i].status='h'; num=jobpcb[i].id;jobtab[num].pcbnum=-1;jobpcb[i].id=-1;
}
if(cmd== 'h') {jobpcb[i].wtime=0; total--;}
jobpcb[i].wtime=jobtab [ jobpcb[i].id ].idx[Index].time;
(*total)++;
}
}
}
void save (){
FILE *fp;
int i;
fp=fopen("pcbtable.txt","a");
fprintf(fp," 文件名 作业编号 执行到指令数 所处状态 等待时间 /n" );
for(i=0;i<3;i++)
fprintf(fp," /t %s /t %d /t %d /t %c /t %d /n" ,
jobpcb[i].filename,jobpcb[i].id,jobpcb[i].exetoIndex,
jobpcb[i].status,jobpcb[i].wtime );
fclose(fp);
}
//作业入队列
void JobEnQueue( int pcbnum,int Index ,int *total){
int num;
char cmd;
if(jobpcb[pcbnum].id>=0){
cmd=jobtab[ jobpcb[pcbnum].id ].idx[ Index ].name;
switch(cmd){
case 'c': insertqueue(&Queue[1],pcbnum); jobpcb[pcbnum].status='r'; break;
case 'i': insertqueue(& Queue[2],pcbnum);jobpcb[pcbnum].status='i'; break;
case 'o': insertqueue(& Queue[3],pcbnum);jobpcb[pcbnum].status='o'; break;
case 'w': insertqueue(& Queue[4],pcbnum);jobpcb[pcbnum].status='w'; break;
case 'h': jobpcb[pcbnum].status='h'; num=jobpcb[pcbnum].id;jobtab[num].pcbnum=-1;jobpcb[pcbnum].id=-1;
}
if(cmd== 'h') {
jobpcb[pcbnum].wtime=0;
printf(" /n/t/t作业 %d 完成/n", pcbnum+1, jobpcb[ pcbnum].status);
(*total)--;
}
else jobpcb[pcbnum].wtime=jobtab [ jobpcb[pcbnum].id ].idx[Index].time;
printf(" /n/t/t作业 %d /n ", pcbnum+1);
printf("/t/t/t/t所处状态 : %c /n",jobpcb[ pcbnum].status);
printf("/t/t还需要时间 %d 秒/n",jobpcb[ pcbnum].wtime);
}
}
//得到队列的首元素
int GetHead(struct Qnode l){
return l.pcbnum[l.head];
}
//执行
void run (){
int i, flag=0, time=10, pcbnum, Index=0, exenum, num, quenum;
char cmd;
int j,m,n;
int total=0;
JobEnQueueInit( &total );
save();
while( total!=0 ){
if( !EmptyQueue( Queue[1]) ){
outqueue(&Queue[1],&pcbnum);
insertqueue(&Queue[0], pcbnum);
else pcbnum=GetHead(Queue[0]);
delay();
jobpcb[ pcbnum].status='e';
printf(" /n/t/t作业 %d /n",pcbnum+1);
printf(" /t/t/t所处状态: %c /t执行了 %d 秒/n", jobpcb[ pcbnum].status, time);
for(i=0;i<3;i++){
if(jobpcb[i].id>=0){
//所有的作业除在就绪队列获执行结束的外等待时间 都间时间片
if( jobpcb[i].status!='r'&&jobpcb[i].status!='h') jobpcb[i].wtime=jobpcb[i].wtime-time;
if(jobpcb[i].wtime<=0){ //查找所有的队列 所在位置
for(j=0;j<5;j++){
for(m=Queue[j].head;m<Queue[j].tail;m++){
if(Queue[j].pcbnum[m]==i) {flag=1;break; }
}
if(flag==1) break;
}
if(flag==1){ //删除该指令
for(n=m;n<Queue[j].tail;n++) Queue[j].pcbnum[n]=Queue[j].pcbnum[n+1];
Queue[j].tail--;
jobpcb[i].exetoIndex++;
Index=jobpcb[i].exetoIndex;
JobEnQueue( i,Index,&total );
}
}
}
}
if(!EmptyQueue( Queue[1]) ){
outqueue(&Queue[0],&pcbnum);
if(jobpcb[pcbnum].wtime>0){
insertqueue(&Queue[1], pcbnum);
jobpcb[pcbnum].status='r';
}
}
printf(" /n/n/t/t 还有/t %d 个作业没有完成 /n",total );
save();
}
}
//初始化
void InitFile(){
int i;
strcpy (jobp[0]," c 20 i 20 o 15 h 0 ");改
strcpy (jobp[1]," i 10 c 20 c 10 h 0 ");
strcpy (jobp[2]," c 30 i 20 c 5 h 0 ");
for(i=0;i<100;i++){
jobpcb[i].exetoIndex=0;
strcpy(jobpcb[i].filename," ");
jobpcb[i].id=-1;
jobpcb[i].status='r';
jobpcb[i].wtime=0;
}
for(i=0;i<100;i++)
jobtab[i].pcbnum=-1;
for(i=0;i<5;i++)
initqueue(&Queue[i]);
//GroupFile[0]=fopen("1.txt","r");
//GroupFile[1]=fopen("2.txt","r");
//GroupFile[2]=fopen("3.txt","r");
}
void main(){
InitFile();
creatpcbline();
run ();
}
设计说明 :
这个程序分了三部分,初始化,创建进程,运行进程,我们三个人分开做,我主要做创建进程的一个函数
即主函数中的 creatpcbline();
设计心得:
操作系统是计算机系统中必不可少的系统软件。它是计算机系统中各种资源的管理者和各种活动的组织者、指挥者。操作系统采用时间片法调度进程,使系统资源得到充分的利用,用户也可以花更少的时间完成更多的工作,这次模拟系统调度进程,让我明白了系统时间片的调度方法,对操作系统理论的学习更加深一层.