一.实验目的和要求
(一) 目的
进程是操作系统最重要的概念之一,进程调度是操作系统的主要内容,本实验要求学生独立地用高级语言编写一个进程调度的模拟程序,调度算法可任意选择或自行设计,本实验可使学生加深对进程调度和各种调度算法的理解。
(二) 要求
1. 设计一个有几个进程并发执行的进程调度模拟程序,每个进程由一个进程控制块(PCB)表示,进程控制块通常应包括下述信息:进程名、进程优先数、进程需要运行的时间、占用CPU的时间以及进程的状态等,且可按照调度算法的不同而增删。
2. 调度程序应包含2—3种不同的调度算法,运行时可以任选一种,以利于各种算法的分析和比较。
3. 系统应能显示或打印各进程状态和参数的变化情况,便于观察。
二.实验内容
1.题目:本程序可选用优先数法或简单轮转法对五个进程进行调度。每个进程处于运行R(run)、就绪W(wait)和完成F(finish)三种状态之一,并假定起始状态都是就绪状态W。
为了便于处理,程序中进程的运行时间以时间片为单位计算。各进程的优先数或轮转时间片数、以及进程需要运行的时间片数,均由伪随机数发生器产生。
进程标识符 |
链指针 |
优先数/轮转时间片数 |
占用CPU时间片数 |
进程所需时间片数 |
进程状态 |
其中:RUN—当前运行进程指针;
HEAD—进程就绪链链首指针;
TAIL—进程就绪链链尾指针。
进程控制块结构如表2-1所示:
2.算法与框图
(1)优先数法。 进程就绪链按优先数大小从大到小排列,链首进程首先投入运行。每过一个时间片,运行进程所需运行的时间片数减1,说明它已运行了一个时间片,优先数也减3。理由是该进程如果在一个时间片中完成不了,优先级应降低一级。接着比较现行进程和就绪链链首进程的优先数,如果仍是现行进程高或者相同,就让现行进程继续运行,否则,调度就绪链链首进程投入运行。原运行进程再按其优先数大小插入就绪链,且改变它们对应的进程状态,直至所有进程都运行完各自的时间片数。
(2)简单轮转法。 进程就绪链按各进程进入的先后次序排列,链首进程首先投入运行。进程每次占用处理机的轮转时间按其重要程度登入进程控制块中的轮转时间片数记录项(相应于优先数法的优先数记录项位置)。每过一个时间片,运行进程占用处理机的时间片数加1,然后比较占用处理机的时间片数是否与该进程的轮转时间片数相等,若相等说明已到达轮转时间,应将现运行进程排到就绪链末尾,调度链首进程占用处理机,且改变它们的进程状态,直至所有进程完成各自的时间片。
三.实验程序清单
#include <stdio.h>
#include <stdlib.h>
#define furthest 5
struct process /*PCB STRUCTURE*/
{
int id;//进程标识符
int priority;//优先级/轮转时间片数记录项
int cputime;//占用CPU时间片数
int alltime;//进程所需时间片数
char state;//进程状态
int next;//链指针
}prochain[furthest+1];//0-5
int procnum;
int rand();
int algo;// 1:简单轮转法 2:优先数法
int run,head,tail,j;//当前运行进程指针 进程就绪链链首指针 进程就绪链链尾指针
void init();
void prisch();
void timesch();
int main() /*MAIN PROGRAM*/
{ agan: printf("type the algorithm is (1:RR,2:PRIO):");
scanf("%d",&algo);
if (algo==2)
{ printf("output of priority.\n");
init();//初始化
prisch();//优先数法
}else
{ if (algo==1)
{ printf("output of round robin.\n");
init();//初始化
timesch();//简单轮转法
}else
{ printf("try again,please\n");
goto agan;//重新输入
}}
for(j=1;j<=40;j++)
{ printf("=");
}
printf("\n\n");
for (j=1;j<=40;j++)
{ printf("=");
}
printf("\n\n");
printf("system finished\n");
return 0;
}
void print() /*PRINT THE RUNNING PROCESS,WAITING QUEUE AND PCB SEQUENCE LIST*/
{ int k,p;
for (k=1;k<=40;k++)
printf("=");
printf("\nrunning proc. ");
printf("waiting queue.");
printf("\n %d ",prochain[run].id);
p=head;
while(p!=0)
{ printf("%5d",p);
p=prochain[p].next;
}
printf("\n");
for (k=1;k<=40;k++)
printf("=");
printf("\n");
printf(" id ");
for (k=1;k<furthest+1;k++)
printf("%5d",prochain[k].id);
printf("\n");
printf("priority ");
for (k=1;k<furthest+1;k++)
printf("%5d",prochain[k].priority);
printf("\n");
printf("cputime ");
for (k=1;k<furthest+1;k++)
printf("%5d",prochain[k].cputime);
printf("\n");
printf("alltime ");
for (k=1;k<furthest+1;k++)
printf("%5d",prochain[k].alltime);
printf("\n");
printf("state ");
for (k=1;k<furthest+1;k++)
printf("%5c",prochain[k].state);
printf("\n");
printf("next ");
for (k=1;k<furthest+1;k++)
printf("%5d",prochain[k].next);
printf("\n");
}
void insert(int q) /*INSERT A PROCESS*/
{ int p,s;
p=head;//q进程前一个进程的进程号
s=prochain[head].next;//q进程后一个进程的进程号
while((prochain[q].priority<prochain[s].priority)&&(s!=0))
{ p=s;
s=prochain[s].next;
}
prochain[p].next=q;
prochain[q].next=s;
}
void insert2()/*PUT A PROCESS ONTO THE TAIL OF THE QUEUE*/
{ prochain[tail].next=run;
tail=run;
prochain[run].next=0;
}
void init() /*CREATE A WAITING QUEUE*/
{ int i;
head=0;
if (algo==2)//优先数法
{
for (i=1;i<=furthest;i++)
{ prochain[i].id=i;//1~5
prochain[i].priority=(rand()+11)%41;//随机生成优先级数
prochain[i].cputime=0;//占用cup时间初始化为0
prochain[i].alltime=(rand())%7+1;//随机生成进程所需时间片数
prochain[i].state='W';//就绪状态
prochain[i].next=0;
if((prochain[i].priority<prochain[head].priority)&&(head!=0))//优先级小于就绪队列中第一个进程
insert(prochain[i].id);//将进程插入就绪队列
else//优先级最大,插入就绪队列链首
{ prochain[i].next=head;
head = prochain[i].id;
}} }else//简单轮转法
{ for (i=1;i<=furthest;i++)
{ prochain[i].id=i;
prochain[i].priority=(rand()+1)%3+1;//随机生成轮转时间片数
prochain[i].cputime=0;//占用cpu时间片数初始化为0
prochain[i].alltime=(rand())%7+1;//随机生成进程所需时间片数
prochain[i].state='W';//就绪状态
prochain[i].next=(i+1)%(furthest+1);
}
head=1;
tail=furthest;
prochain[furthest].next=0;
}
/*运行链首进程*/
run=head;
prochain[run].state='R';
head=prochain[head].next;
prochain[run].next=0;
print();//打印PCB
} void prisch() /*THE PROCESS WITH PRIO ALGORITHM*/
{ while(run!=0)
{
prochain[run].cputime+=1;//CPU时间片数+1
prochain[run].priority-=3;//优先级减3
prochain[run].alltime-=1;//所需时间片数-1
if(prochain[run].alltime<=0)//本进程运行完
{
prochain[run].state='F';
prochain[run].next=0;
if(head!=0)//就绪队列还有进程
{
run=head;
prochain[run].state='R';
head=prochain[head].next;
}
else//就绪队列没有进程了
{
prochain[0].id=prochain[run].id;
run=0;
}
}
else//本进程没有运行完
{
if((prochain[run].priority < prochain[head].priority)&&(head!=0))
{
prochain[run].state='W';
insert(run);
run = head;
prochain[run].state='R';
head = prochain[head].next;
}}
print();
}}
void timesch() /*THE PROCESS WITH RR ALRORITHM*/
{ while(run!=0)
{
prochain[run].alltime-=1;//进程所需总时间片数-1
prochain[run].cputime+=1;//cpu已运行时间片数+1
if(prochain[run].alltime<=0)//本进程已经运行完
{
prochain[run].state='F';//本进程的状态改成完成状态
prochain[run].next=0;
if(head!=0)//就绪队列中还有进程
{
run=head;
prochain[run].state='R';
head=prochain[head].next;
}
else//就绪队列中无进程
{
prochain[0].id=prochain[run].id;
run=0;
}
}else//本进程未运行完成
{ if((prochain[run].cputime==prochain[run].
priority)&&(head!=0))
{
prochain[run].state='W';
prochain[run].cputime=0;
insert2();
run=head;
prochain[run].state='R';
head=prochain[head].next;
}}
printf("%d\n",run);
print();
}}
四.实验结果
1、选择简单轮转法实验结果如下:
2、选择优先数法实验结果如下:
本文来自博客园,作者:一路向北~~,转载请注明原文链接:https://www.cnblogs.com/ylxb2539989915/p/16339086.html