最高優先級算法——進程調度


原創


最近幾周操作系統實習,要求完成幾道題目,下面是自己敲出來的模擬在單處理器情況下的進程調度算法(說算法可能過於高大尚),

采用的是短作業優先調度算法、時間片輪轉調度、最高優先級優先算法三種算法中的最高優先級算法。

題目闡述如下:

                    設計一:進程調度

  設計目的:    

  進程管理是操作系統中的重要功能,用來創建進程、撤消進程、實現進程狀態轉換,它提供了在可運行的進程之間復用CPU的方法。

在進程管理中,進程調度是核心,因為在采用多道程序設計的系統中,往往有若干個進程同時處於就緒狀態,當就緒進程個數大於處

理器數目時,就必須依照某種策略決定哪些進程優先占用處理器。本設計模擬在單處理器情況下的進程調度,目的是加深對進程調度

工作的理解,掌握不同調度算法的優缺點。

  設計內容:

設計程序模擬單處理機系統中的進程調度算法,在短作業優先調度算法、時間片輪轉調度、最高優先級優先算法三種算法中選擇兩種實現。

每個進程由一個進程控制塊(PCB)表示。進程控制塊可以包含如下信息:進程名、優先數、到達時間、需要運行時間、已用CPU時間、進

程狀態等。進程的優先數及需要的運行時間可以事先人為地指定(也可以由隨機數產生)。進程的到達時間為進程輸入的時間。

進程的運行時間以時間片為單位進行計算。

每個進程的狀態可以是就緒W(Wait)、運行R(Run)或完成F(Finish)3中狀態之一。

以下是最高優先級優先算法思想:

就緒進程獲得CPU后都只能運行一個時間片,用已占用CPU時間加1來表示。

如果運行一個時間片后,進程的已占用CPU時間已達到所需要的運行時間,則撤銷該進程,如果運行一個時間片后進程的已占用CPU時間

還未達到所需要的運行時間,也即進程還需要繼續運行,此時應將進程的優先數減1(即降低一級),然后把它插入就緒隊列等待CPU。

每進行一次調度程序都打印一次運行進程、就緒隊列以及各個進程的PCB,以便進行檢查。

重復以上過程,直到所有進程都完成為止。

 

每個PCB進程包括:進程名、優先數、到達時間、需要運行時間、已用CPU時間、進程狀態;采用結構體類型來存儲一個PCB。

采用的數據結構是隊列,創建的進程形成一個雙向隊列(采用雙向隊列容易尋找前驅結點的地址),遍歷隊列,從中找出優先級

最高的PCB取出(相當於調入CPU),將其優先數降低,增加其已用CPU時間,改變其進程狀態;然后判斷其已用CPU時間是否

大於等於需要運行時間,大於將其進程狀態置為完成狀態,否則將此PCB插入隊列尾部,再次在隊列中尋找優先級最高的PCB......

/*
    最高優先級算法 
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 3
#define Time_film 2    //時間片

int count = 0;    //統計進程完成個數 

void print(struct PCB *head);

struct PCB{
    int process_name;    //進程名 
    int priority_number;    //優先數,隨機產生 
    int arrive_time;    //到達時間,為進程的創建時間 
    int need_time;    //需要運行的時間,隨機產生 
    int used_time;    //已用CPU的時間,初始值為0 
    int process_state;    //進程狀態,1表示運行,0表示完成,-1表示就緒,初始值為-1 
    struct PCB *cre;    //前驅指針域
    struct PCB *next;    //后驅指針域
};

void Process_scheduling(struct PCB *head){
    /*
    掃描隊列,尋找最高優先數的PCB,調入CPU運行;
    如果 use_CPU == need_time 撤銷此PCB;
    否則用完一個時間片后放回隊列尾部,繼續掃描;
    */
    //****************************
    struct PCB *Move=head->next;
    struct PCB *Max_Pri=head->next;
    struct PCB *Tail;    //尾指針 
    //****************************
    while(Move!=NULL){
        if(Max_Pri->priority_number < Move->priority_number){
            Max_Pri = Move;
        }                        //尋找最高優先級進程 
        Move = Move->next;
    }
    //****************************
    Move = Max_Pri->cre;        //將最高優先級進程調出
    Move->next = Max_Pri->next;
    if(Move->next != NULL){
        Move = Max_Pri->next;
        Move->cre = Max_Pri->cre;    
    }
    //****************************
    printf("        進程 %d 被調度: \n",Max_Pri->process_name);
    Max_Pri->used_time += Time_film;    //增加CPU占用時間
    if(Max_Pri->used_time >= Max_Pri->need_time){
        Max_Pri->used_time = Max_Pri->need_time;    //進程狀態改變
        Max_Pri->process_state = 0;
        count++;
    }
    else{
        Max_Pri->process_state = 1;
    }
    Max_Pri->priority_number-=1;    //優先數減1
    printf(" %d     %d     %d        %d         %d      %d \n\n",Max_Pri->process_name,Max_Pri->priority_number,Max_Pri->arrive_time,Max_Pri->need_time,Max_Pri->used_time,Max_Pri->process_state);
    if(count == N){    //所有進程執行完畢 
        printf("        所有進程執行完畢!");
        return;
    }
    printf("        就緒隊列:\n");
    print(head);    //輸出就緒隊列
    printf("\n");
    //****************************
    if(Max_Pri->process_state !=0){
        Move = head;
        while( Move->next!=NULL ){    //當被調出進程未完成時將其插入就緒隊列尾部 
            Move = Move->next; 
        }
        Tail = Move;
        Max_Pri->cre = Tail;
        Max_Pri->next = NULL;
        Tail->next = Max_Pri;
        Max_Pri->process_state = -1;
    }
    //****************************
    Process_scheduling(head);
}

void print(struct PCB *head){    //輸出隊列函數 
    if(head->next == NULL){
        printf("就緒隊列已空\n");
        return;
    }
    printf("name priority arr_time need_time use_CPU pro_state\n");
    struct PCB *fry = head->next;
    while(fry != NULL){
        printf(" %d     ",fry->process_name);
        printf("%d     ",fry->priority_number);
        printf("%d        ",fry->arrive_time);
        printf("%d         ",fry->need_time);
        printf("%d      ",fry->used_time);
        printf("%d ",fry->process_state);
        printf("\n");
        fry = fry->next;    
    }
    printf("\n"); 
}

int main(){
    struct PCB *head;    //頭指針
    struct PCB Pro[N+1];    //創建 N+1 個進程
    head = &Pro[0];
    srand(time(0));
    
    //****************************
    //設置進程參數
    Pro[0].process_name = 0;
    Pro[0].cre = NULL;
    Pro[0].next = &Pro[1];
    Pro[0].priority_number = 0;
    int i=0;
    for(i=1;i<=N;i++){
        Pro[i].process_name = i;
        Pro[i].priority_number = rand()%10;
        while(Pro[i].priority_number == 0){
            Pro[i].priority_number = rand()%10;
        }
        Pro[i].arrive_time = i;
        Pro[i].need_time = rand()%7;
        while(Pro[i].need_time == 0){
            Pro[i].need_time = rand()%7;
        }
        Pro[i].used_time = 0;
        Pro[i].process_state = -1;
    }
    for(i=1;i<=N;i++){    //形成雙向隊列
        if( i == N ){
            Pro[i].cre = &Pro[i-1];
            Pro[i].next = NULL;
            break;
        }
        Pro[i].cre = &Pro[i-1];
        Pro[i].next = &Pro[i+1];
    }
    //****************************
    
    printf("        進程初始狀態: \n");
    print(head);    //輸出初始隊列狀態
    
    Process_scheduling(head);    //調用進程調度函數(最高優先級)
    
    return 0;
}

(運行結果部分截圖)

10:58:00 

2018-05-12

 

改進:

上面忽視了進程的到達時間這個因素,會產生致命錯誤:

進程沒有到達,但是其優先級最高,還是會被調用!

必須從已經到達的進程中選擇優先級最高的調入CPU運行,每個進程每次使用一次時間片后必須判斷哪些進程已經到來,然后再

所有到達的進程中選擇優先級最高的調入CPU運行;可以設置一個動態的系統時間 system_time(初始值為最先到達進程的到

達時間)system_time 在每個進程執行完一次后都增加該進程此次執行的時間(這里不指明每次執行時間為時間片是因為當進程

剩下需要的執行時間小於一個時間片后 system_time 不會增加一個時間片),進程每次執行完一個時間片后,將 system_time

每個進程的到達時間進行比較,大於 system_time 則未到達,反之,到達;再從已到達的進程中選擇優先級最高的調入CPU運

行......值得一提的是,若遇到進程到來比較晚( system_time<進程的到達時間)前面的進程都已經執行完成(已從隊列中移除)

則通過 system_time 將找不到合適的進程調入,此時必須通過 “手動”添加系統時間來達到下一個進程的到達時間,然后將其執行。

/*
    最高優先級算法 
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 5
#define Time_film 2    //時間片

int count = 0;    //統計進程完成個數 
int system_time=100; 
int flag=0;
int ff=0;

void print(struct PCB *head);

struct PCB{
    int process_name;    //進程名
    int priority_number;    //優先數,隨機產生 
    int arrive_time;    //進程的到達時間,隨機產生 
    int need_time;    //需要運行的時間,隨機產生 
    int used_time;    //已用CPU的時間,初始值為0 
    int process_state;    //進程狀態,1表示運行,0表示完成,-1表示就緒,初始值為-1 
    struct PCB *cre;    //前驅指針域
    struct PCB *next;    //后驅指針域
};

void Process_scheduling(struct PCB *head){
    /*
    掃描隊列,將最先到達的進程調入運行,若多個進程
    同時到達,選取優先級最高的進程    調入,運行狀態
    的進程用完一個時間片后判斷是否進程是否執行完畢
    或有新進程到達,加入新進程后再次選取優先級最高
    的調入運行,直至進程全部調用完畢。 
    */
     
    //****************************
    struct PCB *Move=head->next;
    struct PCB *Max_Pri=head;
    struct PCB *Tail;    //尾指針 
    //****************************
    
    /*
    while(Move!=NULL){
        if(Max_Pri->arrive_time > Move->arrive_time){    //尋找最早到達的進程 
            Max_Pri = Move;
        }
        Move = Move->next;
    }
    Move=hear->next;
    while(Move!=NULL){    //在幾個同時最早時間到達的進程中選擇優先級最高的 
        if(Max_Pri->arrive_time == Move->arrive_time){
            if(Max_Pri->priority_number>Move->priority_number){
                Max_Pri=Move;
            }
        }
        Move=Move->next; 
    }
    */
    flag=0;
    ff=0;
    while(++flag){
        Move=head->next;
        Max_Pri=head;
        while(Move!=NULL){
            if(Move->arrive_time <= system_time){    //小於等於系統時間的進程說明已經到達,小於系統時間的進程都要相互比較優先級
                if(Move->priority_number>Max_Pri->priority_number){
                    Max_Pri=Move;
                }    
            }
            Move=Move->next;
        }
        if(Max_Pri->cre==NULL){    //說明沒有選出合適進程,需要增加系統時間
            ff=1;
            system_time++; 
        }
        else{
            break;
        }
    }
    if(ff==1){
        printf("暫無進程可執行,等待 %d 后,系統時間為: %d \n\n",flag-1,system_time);
    }
    //****************************
    Move = Max_Pri->cre;        //將上面選擇的進程調入CPU運行
    Move->next = Max_Pri->next;
    if(Move->next != NULL){
        Move = Max_Pri->next;
        Move->cre = Max_Pri->cre;
    }
    //****************************
    printf("        進程 %d 被調度: \n",Max_Pri->process_name);
    Max_Pri->used_time += Time_film;    //增加CPU占用時間
    if(Max_Pri->used_time >= Max_Pri->need_time){
        if(Max_Pri->used_time==Max_Pri->need_time){
            system_time+=Time_film;
        }
        if(Max_Pri->used_time > Max_Pri->need_time){
            system_time+=(Max_Pri->used_time-Max_Pri->need_time);
        }
        Max_Pri->used_time = Max_Pri->need_time;
        Max_Pri->process_state = 0;        //進程狀態改變
        count++;
    }
    else{
        system_time+=Time_film;
        Max_Pri->process_state = 1;
    }
    Max_Pri->priority_number-=1;    //優先數減1
    printf(" %d     %d     %d        %d         %d       %d\n\n",Max_Pri->process_name,Max_Pri->priority_number,Max_Pri->arrive_time,Max_Pri->need_time,Max_Pri->used_time,Max_Pri->process_state);
    if(count == N){    //所有進程執行完畢 
        printf("        所有進程執行完畢!");
        return;
    }
    if(Max_Pri->process_state==1){
        printf("進程 %d 未完成,進入就緒隊列,系統時間為: %d \n\n",Max_Pri->process_name,system_time);
    }
    else{
        printf("進程 %d 已完成,系統時間為: %d \n\n",Max_Pri->process_name,system_time);
    }
    printf("        就緒隊列:\n");
    //****************************
    if(Max_Pri->process_state !=0){
        Move = head;
        while( Move->next!=NULL ){    //當被調出進程未完成時將其插入就緒隊列尾部
            Move = Move->next; 
        }
        Tail = Move;
        Max_Pri->cre = Tail;
        Max_Pri->next = NULL;
        Tail->next = Max_Pri;
        Max_Pri->process_state = -1;
    }
    print(head);
    //****************************
    Process_scheduling(head);
}

void print(struct PCB *head){    //輸出隊列函數 
    if(head->next == NULL){
        printf("就緒隊列已空\n");
        return;
    }
    printf("name priority arr_time need_time use_CPU pro_state\n");
    struct PCB *fry = head->next;
    while(fry != NULL){
        printf(" %d     ",fry->process_name);
        printf("%d     ",fry->priority_number);
        printf("%d        ",fry->arrive_time);
        printf("%d         ",fry->need_time);
        printf("%d      ",fry->used_time);
        printf("%d          ",fry->process_state);
        printf("\n");
        fry = fry->next;
    }
    printf("\n"); 
}

int main(){
    struct PCB *head;    //頭指針
    struct PCB Pro[N+1];    //創建 N+1 個進程-----就緒狀態隊列
    srand(time(0));
    
    //****************************
    //設置就緒狀態進程參數
    head = &Pro[0];
    int i=0;
    for(i=0;i<=N;i++){
        if(i==0){
            Pro[i].process_name = 0;
            Pro[i].cre = NULL;
            Pro[i].next = &Pro[i+1];
            Pro[i].priority_number = -100;
            continue;
        }
        Pro[i].process_name = i;
        Pro[i].priority_number = rand()%10;
        while(Pro[i].priority_number == 0){
            Pro[i].priority_number = rand()%10;
        }
        Pro[i].arrive_time = rand()%10;
        Pro[i].need_time = rand()%7;
        while(Pro[i].need_time == 0){
            Pro[i].need_time = rand()%7;
        }
        Pro[i].used_time = 0;
        Pro[i].process_state = -1;
    }
    for(i=1;i<=N;i++){    //形成雙向隊列
        if( i == N ){
            Pro[i].cre = &Pro[i-1];
            Pro[i].next = NULL;
            break;
        }
        Pro[i].cre = &Pro[i-1];
        Pro[i].next = &Pro[i+1];
    }
    //****************************
    for(i=1;i<=N;i++){    //將最先到達進程的時間設置為系統開始時間 
        if(Pro[i].arrive_time<system_time){ 
            system_time=Pro[i].arrive_time;
        }
    }
    printf("系統時間為: %d \n",system_time);
    //****************************
    
    
    printf("        就緒狀態進程: \n");
    print(head);    //輸出就緒狀態進程 
    
    Process_scheduling(head);    //調用進程調度函數(最高優先級)
    
    return 0;
}

(運行結果部分截圖)

16:31:29

2018-05-18


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM