1. 程式人生 > >作業系統實驗------處理機排程

作業系統實驗------處理機排程

實驗一  處理機排程實驗

一、  實驗目的:

用高階語言編寫和除錯一個程序排程程式,以加深對程序的概念及程序排程演算法的理解。

二、    實驗要求:

   用C++語言實驗對N個程序採用非搶佔式的動態優先權優先演算法的程序排程

三、    實驗內容:

(1)   設計一個有N個程序併發的程序排程程式。程序排程演算法:採用最高優先數優先的排程演算法(即把處理機分配給優先數最高的程序)演算法。

(2)   每個程序有一個程序控制塊(PCB)表示。PCB用結構來描述,包括以下欄位:

l 程序標識ID、

l 優先數,為初始設定的模擬條件

l 到達時間,為初始設定的模擬條件

l 需要執行時間,為初始設定的模擬條件

l 已用CPU時間,為初始設定的模擬條件

l 程序阻塞時間startblock(表示程序在執行startblock個時間片後,程序將進入阻塞狀態),為初始設定的模擬條件

l 程序被阻塞的時間blocktime(表示程序等待blocktime個時間片後,將轉換成就緒狀態),為初始設定的模擬條件,模擬執行I/O操作需要的時間

l 程序狀態state,就緒W(Wait)、執行R(Run)、或完成F(Finish)三種狀態

l 佇列指標next等等。

(3)  優先數改變的規則

程序在就緒佇列中呆一個時間片,優先數增加1;

程序每執行一個時間片,優先數減3;

(4)  執行過程描述

首先按照初始化輸入,按照各程序優先順序高低排列就緒佇列中程序順序,優先順序最高的程序最先獲得CPU控制權執行。如果執行一個時間片後,程序的已佔用CPU時間已達到所需要的執行時間,則撤消該程序,如果執行一個時間片後進程的已佔用CPU時間還未達所需要的執行時間,此時應將程序的優先數減3(即降低一級),如果到了程序需被阻塞的時間點,阻塞程序,然後把它插入阻塞佇列,等待經過blocktime後,再喚醒程序,把它按照優先順序高低,插入就緒佇列相應位置等待CPU。

每進行一次排程程式都列印一次執行程序、就緒佇列、以及各個程序的PCB,以便進行檢查。

重複以上過程,直到所要程序都完成為止。

備註:程序的優先數及需要的執行時間可以事先人為地指定(也可以由隨機數產生)。

程序的到達時間為程序輸入的時間或順序。

參考資料:

部分資料結構說明:

struct pcb { /* 定義程序控制塊PCB */
char name[10];
char state;
int super;
int ntime;
int rtime;

。。。。。。。。。。。。。。。

struct pcb* link;
};

程式碼:

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<stdio.h>
#include<queue>
using namespace std;

typedef struct PCB{
    int Id;//程序標識
    int Number;//優先數
    int ArrivedTime;//到達時間
    int NeedTime;//需要執行時間
    int UserTime;//已用CPU時間
    int BlockTime;//程序被阻塞的時間
    int StartblockTime;//程序阻塞時間
    char stat[6];//程序狀態
    int True;//標誌是否執行結束
    int TrueZuse;
    int InZuSeTime;
};
//定義優先佇列排序
bool operator < (PCB n1,PCB n2)
    {
      return n1.Number<n2.Number;//最大優先
    }
PCB pcb[50];
priority_queue<PCB> q;//就緒佇列
priority_queue<PCB>  Q;//阻塞佇列
int AllTime=0;
int INFI=3;
//將程序插進就緒佇列
void insertq(){
    for (int i=0; i<INFI; i++){
        //判斷是否已經執行結束
        if (pcb[i].True==0)
        {
            q.push(pcb[i]);
        }
    }
}
//判斷是否執行結束
int IsFinish(PCB pcb)
{
    if(pcb.True==1)
    return 1;
    else return 0;
}
//列印程序資訊
void PutOut(PCB pcb)
{
    printf("Id=%d\n",pcb.Id);
    printf("Number=%d\n",pcb.Number);
    printf("ArrivedTime=%d\n",pcb.ArrivedTime);
    printf("NeedTime=%d\n",pcb.NeedTime);
    printf("UserTime=%d\n",pcb.UserTime);
    printf("BlockTime=%d\n",pcb.BlockTime);
    printf("StartblockTime=%d\n",pcb.StartblockTime);
    printf("stat=%s\n",pcb.stat);
    printf("True=%d\n",pcb.True);
    printf("TrueZuse=%d\n",pcb.TrueZuse);
    printf("InZuSeTime=%d\n",pcb.InZuSeTime);
    printf("...........下一個程序詳情............\n");

}
//初始化程序
void init()
{
    pcb[0].Id=0;
    pcb[0].Number=8;
    pcb[0].ArrivedTime=0;
    pcb[0].NeedTime=3;
    pcb[0].UserTime=0;
    pcb[0].StartblockTime=1;
    pcb[0].BlockTime=1;
    pcb[0].stat[0]='w';
    pcb[0].stat[1]='a';
    pcb[0].stat[2]='i';
    pcb[0].stat[3]='t';
    pcb[0].True=0;
    pcb[0].TrueZuse=0;


    pcb[1].Id=1;
    pcb[1].Number=10;
    pcb[1].ArrivedTime=0;
    pcb[1].NeedTime=4;
    pcb[1].UserTime=0;
    pcb[1].StartblockTime=12;
    pcb[1].BlockTime=12;
    pcb[1].stat[0]='w';
    pcb[1].stat[1]='a';
    pcb[1].stat[2]='i';
    pcb[1].stat[3]='t';
    pcb[1].True=0;
    pcb[1].TrueZuse=0;

    pcb[2].Id=2;
    pcb[2].Number=5;
    pcb[2].ArrivedTime=0;
    pcb[2].NeedTime=2;
    pcb[2].UserTime=0;
    pcb[2].StartblockTime=122;
    pcb[2].BlockTime=1222;
    pcb[2].stat[0]='w';
    pcb[2].stat[1]='a';
    pcb[2].stat[2]='i';
    pcb[2].stat[3]='t';
    pcb[2].True=0;
    pcb[2].TrueZuse=0;
}
int main()
{
    init();
    insertq();
    int gg =0;
    AllTime=1;
    while(gg<7){
        //if (q.size()<=0)continue;
        PCB pcbb;  int id=0;
        pcbb = q.top();
        id = pcbb.Id;
        //判斷程序阻塞時間是否到了
        for (int i=0; i<INFI; i++)
        {
            if (pcb[i].UserTime == pcb[i].StartblockTime && pcb[i].TrueZuse!=1)
            {
                //阻塞時間到,插進阻塞佇列
                Q.push(pcb[i]);
                pcb[i].TrueZuse=1;//標記阻塞
                pcb[i].InZuSeTime=AllTime;
            }
        }
        if (!IsFinish(pcb[id]))
        pcb[id].UserTime++;
        //判斷是否執行結束
        if (pcb[id].UserTime>=pcb[id].NeedTime)
        {
            pcb[id].True=1;
            pcb[id].stat[0]='F';
            pcb[id].stat[1]='i';
            pcb[id].stat[2]='n';
            pcb[id].stat[3]='i';
            pcb[id].stat[4]='s';
            pcb[id].stat[5]='h';
        }
        //減優先數
        pcb[id].Number=pcb[id].Number-3;
        //就緒佇列中每個加1
        for (int i=0; i<INFI; i++)
        {
            //判斷是否在就緒中列中
            if (pcb[i].TrueZuse==0 && pcb[i].Id!=id&&!IsFinish(pcb[i]))
            {
                //優先數加一
                pcb[i].Number++;
            }
        }
        if (!Q.empty())
        {
            //判斷阻塞時間是否結束
            for (int i=0; i<INFI; i++)
            {
                //判斷是否在阻塞佇列中
                if (pcb[i].TrueZuse==1)
                {
                    //判斷阻塞時間是否結束
                    if (pcb[i].BlockTime == AllTime - pcb[i].InZuSeTime)
                    {
                        pcb[i].TrueZuse=0;
                    }
                }
            }
        }
        //列印所有程序資訊
        for (int i=0; i<INFI; i++)
        {
            PutOut(pcb[i]);
            q.pop();
        }
        insertq();
        gg++;
        AllTime++;
        printf("...........第%d時間片............\n",gg);
    }
}