進程調度模擬程序


1.    目的和要求

1.1.           實驗目的

用高級語言完成一個進程調度程序,以加深對進程的概念及進程調度算法的理解。

1.2.           實驗要求

1.2.1例題:設計一個有 N個進程並發執行的進程調度模擬程序。

進程調度算法:采用最高優先級優先的調度算法(即把處理機分配給優先級最高的進程)和先來先服務(若優先級相同)算法。

(1).  每個進程有一個進程控制塊(PCB)表示。進程控制塊包含如下信息:進程名、優先級、到達時間、需要運行時間、已用CPU時間、進程狀態等等。

(2).  進程的優先級及需要的運行時間可以事先人為地指定,進程的運行時間以時間片為單位進行計算。

(3).  每個進程的狀態可以是就緒 r(ready)、運行R(Running)、或完成F(Finished)三種狀態之一。

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

(5).  如果運行一個時間片后,進程的已占用 CPU時間已達到所需要的運行時間,則撤消該進程,如果運行一個時間片后進程的已占用CPU時間還未達所需要的運行時間,也就是進程還需要繼續運行,此時應將進程的優先數減1(即降低一級),然后把它插入就緒隊列等待調度。

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

(7).  重復以上過程,直到所要進程都完成為止。

 

1.2.2實驗題A:編寫並調試一個模擬的進程調度程序,采用“最高優先數優先”調度算法對N(N不小於5)個進程進行調度。

“最高優先級優先”調度算法的基本思想是把CPU分配給就緒隊列中優先數最高的進程。

(1). 靜態優先數是在創建進程時確定的,並在整個進程運行期間不再改變。

(2). 動態優先數是指進程的優先數在創建進程時可以給定一個初始值,並且可以按一定規則修改優先數。例如:在進程獲得一次CPU后就將其優先數減少1,並且進程等待的時間超過某一時限(2個時間片時間)時增加其優先數等。

(3). (**) 進程的優先數及需要的運行時間可以事先人為地指定,(也可以由隨機數產生)。

(4). (**)在進行模擬調度過程可以創建(增加)進程,其到達時間為進程輸入的時間。

 

1.2.3實驗題B:編寫並調試一個模擬的進程調度程序,采用“基於時間片輪轉法”調度算法對N(N不小於5)個進程進行調度。 “輪轉法”有簡單輪轉法、多級反饋隊列調度算法。

(1). 簡單輪轉法的基本思想是:所有就緒進程按 FCFS排成一個隊列,總是把處理機分配給隊首的進程,各進程占用CPU的時間片長度相同。如果運行進程用完它的時間片后還未完成,就把它送回到就緒隊列的末尾,把處理機重新分配給隊首的進程。直至所有的進程運行完畢。(此調度算法是否有優先級?)

 (2). 多級反饋隊列調度算法的基本思想是:

將就緒隊列分為N級(N=3~5),每個就緒隊列優先數不同並且分配給不同的時間片:隊列級別越高,優先數越低,時間片越長;級別越小,優先數越高,時間片越短。

系統從第一級調度,當第一級為空時,系統轉向第二級隊列,.....當處於運行態的進程用完一個時間片,若未完成則放棄CPU,進入下一級隊列。

當進程第一次就緒時,進入第一級隊列。

(3). (**)考慮進程的阻塞狀態B(Blocked)增加阻塞隊列。進程的是否阻塞和阻塞的時間由產生的“隨機數”確定(阻塞的頻率和時間長度要較為合理)。注意進程只有處於運行狀態才可能轉換成阻塞狀態,進程只有處於就緒狀態才可以轉換成運行狀態。

2.    實驗內容

根據指定的實驗課題:A(1),A(2),B(1)和B(2)

完成設計、編碼和調試工作,完成實驗報告。

注:帶**號的條目表示選做內容。

 3.    實驗環境

可以選用Turbo C作為開發環境。也可以選用Windows下的VB,CB等可視化環境,利用各種控件較為方便。自主選擇實驗環境。

4.    實驗原理及核心算法參考程序段

     動態優先數(優先數只減不加):

 

 

 

5.參考代碼如下:

#include <stdio.h>
#include <stdlib.h>

struct PCB{
    char p_name[20];
    int p_priority;
    int p_needTime;a
    int p_runTime;
    char p_state;
    struct PCB* next;
};

void HighPriority();
void RoundRobin();
void Information();
char Choice();
struct PCB* SortList(PCB* HL);

int main()
{
    Information();
    char choice = Choice();
    switch(choice)
    {
        case '1':
            system("cls");
            HighPriority();
            break;
        case '2':
            system("cls");
            RoundRobin();
            break;
        default:
            break;
    }
    system("pause");
    return 0;
}

void Information()
{
    printf("\n\n");
    printf("              *********************************************             \n");
    printf("                            模擬進程調度算法\n");
    printf("              *********************************************             \n\n\n");    
    printf("                       班    級:  網絡工程班\n");
    printf("                       姓    名:  張文雅\n");
    printf("                       學    號:  201306114136\n");
    printf("                       實驗日期: 2015年05月17日\n\n\n\n\n\n");
    printf("                         按回車鍵進入演示程序");
    getchar();
    system("cls");
}
char Choice()
{
    printf("\n\n");
    printf("              *********************************************             \n");
    printf("                              進程調度演示\n");
    printf("              *********************************************             \n\n\n");    
    printf("                        1.演示最高優先數優先算法。\n");
    printf("                        2.演示輪轉法算法。\n");
    printf("                        3.退出程序。\n\n\n\n");
    printf("                            選擇進程調度方法:");     
    char ch = getchar();
    return ch;
    system("cls");
}
void HighPriority()
{
    struct PCB *processes, *pt;
    //pt作為臨時節點來創建鏈表
    processes = pt = (struct PCB*)malloc(sizeof(struct PCB));    
    for (int i = 0; i != 5; ++i)
    {
        struct PCB *p = (struct PCB*)malloc(sizeof(struct PCB));
        printf("進程號No.%d:\n", i);
        printf("輸入進程名:");
        scanf("%s", p->p_name);
        printf("輸入進程優先數:");
        scanf("%d", &p->p_priority);
        printf("輸入進程運行時間:");
        scanf("%d", &p->p_needTime);
        p->p_runTime = 0;
        p->p_state = 'W';
        p->next = NULL;
        pt->next = p;
        pt = p;
        printf("\n\n");
    }
    getchar();  //接受回車
    //processes作為頭結點來存儲鏈表
    processes = processes->next;
    int cases = 0;
    struct PCB *psorted = processes;
    while (1)
    {
        ++cases;
        pt = processes; 
        //對鏈表按照優先數排序
        //psorted用來存放排序后的鏈表
        psorted = SortList(psorted);
        printf("The execute number: %d\n\n", cases);
        printf("**** 當前正在運行的進程是:%s\n", psorted->p_name);
        psorted->p_state = 'R';
        printf("qname    state    super    ndtime    runtime\n");
        printf("%s\t%c\t%d\t%d\t%d\t\n\n", psorted->p_name, psorted->p_state, psorted->p_priority, psorted->p_needTime, psorted->p_runTime);
        pt->p_state = 'W';
        psorted->p_runTime++;
        psorted->p_priority--;
        printf("**** 當前就緒狀態的隊列為:\n\n");
        //pt指向已經排序的隊列
        pt = psorted->next;
        while (pt != NULL)
        {
            printf("qname    state    super    ndtime    runtime\n");
            printf("%s\t%c\t%d\t%d\t%d\t\n\n", pt->p_name, pt->p_state, pt->p_priority, pt->p_needTime, pt->p_runTime);
            pt = pt->next;
        }
        //pt指向已經排序的鏈表,判斷鏈表是否有已用時間啊等於需要時間的
        pt = psorted;
        struct PCB *ap;
        ap = NULL; //ap指向pt的前一個節點
        while (pt != NULL)
        {
            if (pt->p_needTime == pt->p_runTime)
            {
                if (ap == NULL)
                {
                    pt = psorted->next;
                    psorted = pt;
                }
                else
                    ap->next = pt->next;
            }
            ap = pt;
            pt = pt->next;
        }
        if (psorted->next == NULL)
            break;
        getchar();
    }
}
struct PCB* SortList(PCB* HL)
{
    struct PCB* SL;
    SL = (struct PCB*)malloc(sizeof(struct PCB));
    SL = NULL;

    struct PCB* r = HL;
    while (r != NULL)
    {
        struct PCB* t = r->next;
        struct PCB* cp = SL;
        struct PCB* ap = NULL;
        while (cp != NULL)
        {
            if (r->p_priority > cp->p_priority)
                break;
            else
            {
                ap = cp;
                cp = cp->next;
            }
        }
        if (ap == NULL)
        {
            r->next = SL;
            SL = r;
        }
        else
        {
            r->next = cp;
            ap->next = r;
        }
        r = t;
    }
    return SL;
}
//輪轉算法
void RoundRobin()
{
    struct PCB *processes, *pt;
    //pt作為臨時節點來創建鏈表
    processes = pt = (struct PCB*)malloc(sizeof(struct PCB));    
    for (int i = 0; i != 5; ++i)
    {
        struct PCB *p = (struct PCB*)malloc(sizeof(struct PCB));
        printf("進程號No.%d:\n", i);
        printf("輸入進程名:");
        scanf("%s", p->p_name);
        printf("輸入進程運行時間:");
        scanf("%d", &p->p_needTime);
        p->p_runTime = 0;
        p->p_state = 'W';
        p->next = NULL;
        pt->next = p;
        pt = p;
        printf("\n\n");
    }
    getchar();  //接受回車
    //processes作為頭結點來存儲鏈表
    processes = processes->next;
    int cases = 0;
    while (1)
    {
        ++cases;
        pt = processes; 
        printf("The execute number: %d\n\n", cases);
        printf("**** 當前正在運行的進程是:%s\n", pt->p_name);
        pt->p_state = 'R';
        printf("qname    state    super    ndtime    runtime\n");
        printf("%s\t%c\t%d\t%d\t%d\t\n\n", pt->p_name, pt->p_state, pt->p_priority, pt->p_needTime, pt->p_runTime);
        pt->p_state = 'W';
        pt->p_runTime++;
        pt->p_priority--;
        printf("**** 當前就緒狀態的隊列為:\n\n");
        pt = pt->next;
        while (pt != NULL)
        {
            printf("qname    state    super    ndtime    runtime\n");
            printf("%s\t%c\t%d\t%d\t%d\t\n\n", pt->p_name, pt->p_state, pt->p_priority, pt->p_needTime, pt->p_runTime);
            pt = pt->next;
        }
        //檢測是否運行時間等於需要時間,是的話從隊列里面刪除,不是的話加到隊列最尾部
        pt = processes;
        if (pt->p_needTime == pt->p_runTime)
        {
            pt->p_state = 'C';
            pt = processes->next;
            processes = pt;
        }
        else
        {
            if (pt ->next != NULL)
            {
                //尋找最后一個節點
                while (pt->next != NULL)
                    pt = pt->next;
                struct PCB* ptem;//臨時節點用來幫助把頭結點插到尾部
                ptem = processes->next;
                pt->next = processes;
                processes->next = NULL;
                processes = ptem;
            }
        }
        pt = processes;
        if (pt == NULL)
            break;
        getchar();
    }
}



運行結果:
x



 實驗總結:編代碼需要細心以及耐心,一開始錯誤連連,通過參考資料,不斷修整代碼,不厭其煩地糾正一個個錯誤,直至運行成功與運算正確,這個過程雖略有辛苦,但也充滿了歡樂,正是所謂的樂在苦中吧。


免責聲明!

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



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