一、目的和要求
- 目的
進程是操作系統最重要的概念之一,進程調度是操作系統的主要內容,本實驗要求學生獨立地用高級語言編寫一個進程調度程序,調度算法可任意選擇或自行設計,本實驗可使學生加深對進程調度和各種調度算法的理解。
- 要求
- 設計一個有幾個進程併發執行的進程調度程序,每個進程由一個進程控制塊(PCB)表示,進程控制塊通常應包括下述信息:進程名,進程優先數,進程需要運行的時間,佔用CPU的時間以及進程的狀態等,且可按照調度算法的不同而增刪。
- 調度程序應包含2—3種不同的調度算法,運行時可以任選一種,以利於各種方法的分析和比較。
- 系統應能顯示或打印各進程狀態和參數的變化情況,便於觀察。
二、示例
- 題目 本程序可選用優先數法或簡單輪轉法對五個進程進行調度。每個進程處於運行R(run)、就緒W(wait)和完成F(finish)三種狀態之一,並假定起始狀態都是就緒狀態W。
爲了便於處理,程序中進程的運行時間以時間片爲單位計算。各進程的優先數或輪轉時間片數、以及進程需要運行的時間片數,均由僞隨機數發生器產生。
進程控制塊結構如表2-1所示:
表2-1 PCB
進程標識符 |
鏈指針 |
優先數/輪轉時間片數 |
佔用CPU時間片數 |
進程所需時間片數 |
進程狀態 |
進程控制塊鏈結構如圖2-1所示:
RUN HEAD TAIL
…
圖2-1 進程控制塊鏈結構
其中:RUN—當前運行進程指針;
HEAD—進程就緒鏈鏈首指針;
TAIL—進程就緒鏈鏈尾指針。
2. 算法與框圖 程序框圖如圖2-2所示。
圖2-2 進程調度框圖
(1)優先數法。 進程就緒鏈按優先數大小從大到小排列,鏈首進程首先投入運行。每過一個時間片,運行進程所需運行的時間片數減1,說明它已運行了一個時間片,優先數也減3。理由是該進程如果在一個時間片中完成不了,優先級應降低一級。接着比較現行進程和就緒鏈鏈首進程的優先數,如果仍是現行進程高或者相同,就讓現行進程繼續運行,否則,調度就緒鏈鏈首進程投入運行。原運行進程再按其優先數大小插入就緒鏈,且改變它們對應的進程狀態,直至所有進程都運行完各自的時間片數。
(2)簡單輪轉法。 進程就緒鏈按各進程進入的先後次序排列,鏈首進程首先投入運行。進程每次佔用處理機的輪轉時間按其重要程度登入進程控制塊中的輪轉時間片數記錄項(相應於優先數法的優先數記錄項位置)。每過一個時間片,運行進程佔用處理機的時間片數加1,然後比較佔用處理機的時間片數是否與該進程的輪轉時間片數相等,若相等說明已到達輪轉時間,應將現運行進程排到就緒鏈末尾,調度鏈首進程佔用處理機,且改變它們的進程狀態,直至所有進程完成各自的時間片。
#include <stdio.h>
#include <stdlib.h>
#define furthest 4
void init();
void prisch();
void timesch();
struct process /*PCB STRUCTURE*/
{
int id;
int priority;
int cputime;
int alltime;
char state;
int next;
}prochain[furthest+1];
int procnum;
int rand();
int algo;
int run,head,tail,j;
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");
}
void printEqual(){
int k;
for (k=1;k<=40;k++)
printf("=");
}
void print()
{
int k,p;
printEqual();
printf("\nrunning proc. %d",prochain[run].id);
printf("\nwaiting queue.");
printf("\n%d",prochain[run].id);
p=head;
while(p!=0){
printf("%5d",p);
p=prochain[p].next;
}
printf("\n");
printEqual();
printf("\n");
printf("id");
for (k=1;k<furthest+1;k++)
printf("%5d",prochain[k].id);
if(algo == 2){
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");
}
insert(int q) /*INSERT A PROCESS*/
{
int p,s;
p=head;
s=prochain[head].next;
while((prochain[q].priority<prochain[s].priority)&&(s!=0)){
p=s;
s=prochain[s].next;
}
prochain[p].next=q;
prochain[q].next=s;
}
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+1;i++){
prochain[i].id=i;
prochain[i].priority=(rand()+11)%41;
prochain[i].cputime=0;
prochain[i].alltime=(rand()+1)%8;
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+1;i++){
prochain[i].id=i;
prochain[i].priority=(rand()+1)%3+1;
prochain[i].cputime=0;
prochain[i].alltime=(rand()+1)%7;
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();
}
void timesch() /*THE PROCESS WITH RR ALRORITHM*/
{
while(run!=0){
prochain[run].alltime-=1;
prochain[run].cputime+=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;}
}
print();
}
}
void prisch(){
while(run!=0){
prochain[run].cputime+=1;
prochain[run].priority-=3;
prochain[run].alltime-=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();
}
}