作業系統之處理機排程
阿新 • • 發佈:2019-02-05
題目描述:
在處理機三級排程系統中,程式設計模擬作業排程與程序排程。作業排程採用短作業優先的方式,程序排程採用優先順序方式或時間片輪轉方式。
原始碼:
#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; }