1. 程式人生 > >作業系統之處理機排程

作業系統之處理機排程

題目描述:

在處理機三級排程系統中,程式設計模擬作業排程與程序排程。作業排程採用短作業優先的方式,程序排程採用優先順序方式或時間片輪轉方式。

原始碼:

#include <iostream>
#include <stdlib.h>
#include <cstdio>
#define TIMELIMIT 6
#define PriLimit 5
#define work 5
using namespace std;

struct JCB     //作業
{
    int jname;    //作業名
    int start;    //到達時間
    int priority;    //優先順序
    int worktime;    //工作時間
    JCB *next;    //連結指標
};

struct PCB
{

    int pname;    //程序名
    int time;    //程序執行時間
    char state;    //執行狀態
    PCB* next;
};

void CreateJob(JCB* jobtable,int name)    //建立作業,將作業放入作業排程表
{
    //隨機生成一個作業
    JCB *p = new JCB;
    p->jname=name;
    p->start = rand()%5+1;
    p->worktime = rand()%TIMELIMIT+1;
    p->priority = rand()%PriLimit+1;
    p->next = NULL;

    JCB* now = jobtable;
    if(now->next==NULL)
    {
        now->next = p;
    }
    else
    {
        if(p->start <= now->next->start)//新插入的作業到達時間比表中的第一個小,將新到的插入到表頭
        {
            p->next = now->next;
            now->next = p;
        }
        else//新插入的作業到達時間比表中的第一個大,向後查詢
        {
            JCB *q = now->next;
            while( (p->start > q->start) && (q->next!=NULL) )
            {
                q = q->next;
            }
            if( (p->start > q->start) && q->next==NULL) //比所有的都大,放到最後
            {
                q->next = p;
            }
            else if(p->start <= q->start)
            {
                JCB *t = now->next;
                while(t->next!=q)  //找到前驅節點
                {
                    t = t->next;
                }
                t->next = p;
                p->next = q;
            }
        }
    }
}

void AddHoubei(JCB *jobtable,JCB *p,JCB *&jhead)    //將作業p放入後備佇列jhead,按短作業優先放置
{
    JCB* q = jobtable;
    while(q->next!=p && q->next!=NULL)// 找到p的前驅節點
    {
        q = q->next;
    }
    if(q->next==p)
    {
        q->next = p->next;
        p->next = NULL;
    }

    if(jhead==NULL)
    {
        jhead = p;
    }
    else
    {
        if(p->worktime <= jhead->worktime)//優先順序小的放在前邊
        {
            p->next = jhead;
            jhead = p;
        }
        else
        {
            JCB *q = jhead;
            while( (p->worktime > q->worktime) && (q->next!=NULL) )
            {
                q = q->next;
            }
            if( (p->worktime > q->worktime) && q->next==NULL) //比所有的都大,放到最後
            {
                q->next = p;
            }
            else if(p->worktime <= q->worktime)
            {
                JCB *t = jhead;
                while(t->next!=q)  //找到前驅節點
                {
                    t = t->next;
                }
                t->next = p;
                p->next = q;
            }
        }
    }
}

void CreateProcess(PCB* &head,PCB* &tail,JCB* &jhead)    //建立新程序
{
    PCB* p = new PCB;
    p->pname = jhead->jname;
    p->state = 'R';    //就緒狀態
    p->time = jhead->worktime;        //程序工作時間

    if(tail==NULL)
    {
        //就緒佇列還是空的,則第一次賦值
        head = p;
        tail = head;
        tail->next = head;
    }
    else
    {
        //就緒佇列不為空
        tail->next = p;
        tail = p;
        p->next = head;
    }

}

void DropPro(PCB* &head,PCB* &tail,PCB* &chead,PCB* &ctail)    //將隊首程序,推出迴圈就緒佇列
{
    PCB* p = head;        //儲存頭節點
    head = head->next;    //頭結點指向他的下一個節點
    tail->next = head;    //將就緒佇列尾節點直接指向新的頭節點
    p->next = NULL;        //將分離出來的原來的頭節點的next設為空NULL

    if(ctail==NULL)
    {
        //已完成程序佇列還是空的,則第一次賦值
        chead = p;
        ctail = chead;
    }
    else
    {
        //已完成程序佇列不為空,則將當前已完成程序放到佇列尾部
        ctail->next = p;
        ctail = ctail->next;
    }
}

void Work(PCB* now)    //當前程序執行
{
    now->time--;
}

void NextPro(PCB* &head,PCB* &tail)    //當前程序已執行了一個時間片,將其置於迴圈佇列尾端。即將head和tail向前推進一次
{
    head = head->next;
    tail = tail->next;
}
void printRQ(PCB* head,int readynum)    //列印當前就緒佇列
{
    PCB* p = head;
    printf("\t--- 就緒佇列 ---\n");
    printf("程序名\t");
    printf("所需時間\t");
    printf("程序狀態\n");
    if(readynum==0)
    {
        //就緒佇列已空
        printf("空\n");
        return ;
    }
    while(p->next!=head)
    {
        printf("%d\t",p->pname);
        printf("%d\t\t",p->time);
        printf("%c\n",p->state);
        p = p->next;
    }
    printf("%d\t",p->pname);
    printf("%d\t\t",p->time);
    printf("%c\n",p->state);
}

void printCQ(PCB* chead,PCB* ctail)    //列印當前已完成程序佇列
{
    PCB* p = chead;
    printf("\t--- 已完成程序 ---\n");
    printf("程序名\t");;
    printf("程序狀態\n");
    if(chead==NULL)
    {
        //已完成程序佇列佇列已空
        printf("空\n");
        return ;
    }
    while(p!=ctail)
    {
        printf("%d\t",p->pname);
        printf("%c\n",p->state);
        p = p->next;
    }
    printf("%d\t",p->pname);
    printf("%c\n",p->state);
}
void printJQ(JCB* jhead)    //列印當前後備佇列
{
    JCB * p = jhead;
    printf("\t--- 後備佇列 ---\n");
    printf("作業名\t");
    printf("到達時間\t");
    printf("工作時間\n");
    if(jhead==NULL)
    {
        printf("空\n");
        return ;
    }
    while(p->next!=NULL)
    {
        printf("%d\t",p->jname);
        printf("%d\t\t",p->start);
        printf("%d\n",p->worktime);
        p = p->next;
    }
    printf("%d\t",p->jname);
    printf("%d\t\t",p->start);
    printf("%d\n",p->worktime);
}
void printProInfo(PCB* now)    //列印當前程序資訊
{
    if(now==NULL)
    {
        printf("當前沒有程序\n");
        return ;
    }
    printf("\t--- 執行佇列 ---\n");
    printf("程序名:\t");
    printf("執行時間:\t");
    printf("程序狀態:\n");
    printf("%d\t",now->pname);
    printf("%d\t\t",now->time);
    printf("%c\n",now->state);
}
void printAllJobInfo(JCB* jhead)    //輸出作業排程表
{
    JCB* p = jhead->next;
    printf("\t--- 作業排程表 ---\n");
    printf("作業名\t");
    printf("到達時間\t");
    printf("工作時間\n");
    while(p!=NULL)
    {
        printf("%d\t",p->jname);
        printf("%d\t\t",p->start);
        printf("%d\n",p->worktime);
        p = p->next;
    }
}

int main()
{
    PCB *head=NULL,*tail=NULL;    //就緒佇列
    JCB *jhead=NULL;    //後備佇列
    PCB *chead=NULL,*ctail=NULL;    //已完成程序佇列
    JCB *jobtable = new JCB;    //作業排程表
    int tablenum=5;    //作業排程表中作業數量
    int houbeinum=0;    //後備佇列的作業數量
    int readynum=0;     //就緒佇列的作業數量
    jobtable->next = NULL;
    for(int i=1; i<6; i++)
        CreateJob(jobtable,i);
    printAllJobInfo(jobtable);    //輸出作業排程表
    printf("\t---開始時間片輪轉---\n");
    printf("********************************\n");
    int curtime=0;
    while(readynum!=0 || houbeinum!=0 || tablenum!=0)     //直到就緒佇列為空 且 後備佇列為空 且 作業排程表為空,退出迴圈
    {
        printf("當前系統時間為%d\n",curtime);
        JCB* p = jobtable->next;
        while(p!=NULL)
        {
            if(p->start==curtime)     //有作業到達,將作業放入後備佇列,並按短作業優先放置
            {
                JCB *t = p->next;
                printf("將作業%d投入到後備佇列\n",p->jname);
                AddHoubei(jobtable,p,jhead);
                printAllJobInfo(jobtable);     //輸出排程表
                printJQ(jhead);                 //輸出後備佇列
                houbeinum++;    //後備佇列
                tablenum--;    //作業排程表
                p = t;
            }
            else
            {
                p = p->next;
            }
        }
        //
        //
        if(readynum==3)     //已滿
        {
            printJQ(jhead);       //輸出後備佇列
            printRQ(head,readynum);      //輸出就緒佇列
        }
        else     //未滿,從後備佇列中將作業放入就緒佇列
        {
            if(houbeinum!=0&&readynum<3)     //後備佇列不為空並且就緒佇列不滿
            {
                CreateProcess(head,tail,jhead);    //將作業投入到就緒佇列
                printf("將作業%d投入到就緒佇列\n",jhead->jname);

                jhead = jhead->next;    //指向後備佇列下一個作業
                readynum++;    //就緒佇列
                houbeinum--;    //後備佇列
                printJQ(jhead);       //輸出後備佇列
                printRQ(head,readynum);      //輸出就緒佇列
            }
        }

        //已空就算了
        PCB* now = head;
        if(now!=NULL)     //當前就緒佇列不為空時執行程序
        {
            //將該程序放入執行佇列
            //rhead = now;
            printf("將%d程序放入執行佇列\n",now->pname);
            printProInfo(now);
            Work(now);    //執行當前程序

            if(now->time==0)
            {
                now->state = 'C';    //設定程序為已完成狀態
                printf("# 程序%d已完成,退出就緒佇列\n",now->pname);
                DropPro(head,tail,chead,ctail);    //推出迴圈就緒佇列
                printCQ(chead,ctail);
                readynum--;
                if(readynum==0)
                {
                    head = 0;
                    tail = 0;
                }
            }
            else
            {
                NextPro(head,tail);    //已完成,將其置於迴圈佇列尾端。即將head和tail向前推進一次
            }

        }
        curtime++;
        printf("--------------------------------\n");
    }
    printf("********************************\n");
    return 0;
}