實驗一: 程序狀態轉換及PCB的模擬
實驗目的
1)加深對程序概念的理解。
2)深入瞭解程序控制塊和程序狀態之間的轉換。
3)掌握程序排程演算法。
實驗預備知識
1)程序的狀態
2)程序的結構——PCB
程序都是由一系列操作(動作)所組成,通過這些操作來完成其任務。因此,不同的程序,其內部操作也不相同。在作業系統中,描述一個程序除了需要程式和私有資料之外,最主要的是需要一個與動態過程相聯絡的資料結構,該資料結構用來描述程序的外部特性(名字、狀態等)以及與其它程序的聯絡(通訊關係)等資訊,該資料結構稱為程序控制塊(PCB,Process Control Block)。
程序控制塊PCB與程序一一對應,PCB中記錄了系統所需的全部資訊、用於描述程序情況所需的全部資訊和控制程序執行所需的全部資訊。因此,系統可以通過程序的PCB來對程序進行管理。
實驗步驟
1)設計一個有 N個程序共行的程序排程程式。
2)程序排程演算法:採用最高優先數優先的排程演算法(即把處理機分配給優先數最高的程序)。每個程序有一個程序控制塊( PCB)表示。程序控制塊可以包含如下資訊:程序名、優先數、到達時間、需要執行時間、已用CPU時間、程序狀態等等。程序的優先數及需要的執行時間可以事先人為地指定(也可以由隨機數產生)。程序的到達時間為程序輸入的時間。程序的執行時間以時間片為單位進行計算。每個程序的狀態可以是就緒 W(Wait)、執行R(Run)、或阻塞F(Finish)三種狀態之一。就緒程序獲得 CPU後都只能執行一個時間片。用已佔用CPU時間加1來表示。如果執行一個時間片後,程序的已佔用 CPU時間已達到所需要的執行時間,則撤消該程序,如果執行一個時間片後進程的已佔用CPU時間還未達所需要的執行時間,也就是程序還需要繼續執行,此時應將程序的優先數減1(即降低一級),然後把它插入就緒佇列等待CPU。每進行一次排程程式都列印一次執行程序、就緒佇列、以及各個程序的 PCB,以便進行檢查。
3)重複以上過程,直到所要程序都完成為止。
排程演算法的流程圖如下 :
實驗結論
1)給出實驗源程式(附有詳細註釋)
2)程式執行截圖
#include <stdio.h> #include <stdlib.h> typedef struct pcb { int name; // 程序的名稱 char state;// 程序的狀態 int arrivetime; //程序的到達時間 int runtime;// 程序的執行時間 int cputime;//cpu佔用的時間 int count;//優先數 struct pcb *next; }pcb; pcb *head = NULL; // 正常對列 pcb *head1 = NULL; // 未到達的對列 int n = 0;// 程序的數量 //建立頭指標 void createhead() { pcb *p = (pcb*)malloc(sizeof(pcb));// 建立頭指標 head = p; pcb *q = (pcb*)malloc(sizeof(pcb));// 建立頭指標 head1 = q; } void sort()// 按照優先數進行排序 { pcb* t = head; pcb *q,*p,*r; int max; while(t->next != NULL) { p = t->next; r = t->next; max = r->count; while(r!= NULL) { if(r->count > max) { max = r->count; p = r; } r = r->next; }// p指向count最大的那一個數 q = t; while (q->next != p) q = q->next; if(t->next != p) { q->next = p->next; p->next = t->next; t->next = p; }// 插入進行排序按照優先數 t = t->next; } } bool create() //建立pcb操作 { createhead(); pcb *p = head; pcb *q = head1; printf("請輸入程序數目:"); scanf("%d",&n); pcb *temp; for(int i=1;i<=n;i++ )//尾插法建立就緒佇列 { temp = (pcb*)malloc(sizeof(pcb)); if(!temp) return false; printf("請輸入程序%d的要求執行時間,程序優先數,到達時間:",i); scanf("%d %d %d",&(temp->runtime),&(temp->count),&(temp->arrivetime)); temp->cputime = 0; temp->name=i; temp->next = NULL; temp->state='W'; if(temp->arrivetime!=0) // 對到達時間進行判斷 { q->next = temp; q = temp; } else { p->next = temp; p = temp; } } sort(); // 排序 return true; } void destory(pcb *rp)// 撤銷操作 { printf("****************程序%d已完成****************\n",rp->name); pcb *q = rp->next; head->next = q; free(rp); } void display(pcb *rp) // 展示當前的資訊 { printf("程序名字:%d",rp->name); printf("\n程序優先順序:%d",rp->count); printf("\n程序所佔時間片:%d",rp->runtime); printf("\n程序已執行時間:%d",rp->cputime); printf("\n程序當前狀態:%c",rp->state); printf("\n=====================================\n"); } void arrivetime()// 對於到達時間-1的操作 { pcb *q = head1->next; pcb *r,*t; while(q!=NULL) // 判斷到達時間是否為0 此時是否到達 { q->arrivetime--; if(q->arrivetime==0) { t = head1; while(t->next!=q) t = t->next; t->next = q->next; r = head->next; q->next = r; head->next = q; } q = q->next; } } void runpcb(pcb *rp) { rp->cputime++; //修改cpu佔用的時間 arrivetime(); printf("----------正在執行的程序----------\n"); // 輸出正在執行的佇列 display(rp); if(rp->cputime==rp->runtime) { destory(rp); } else { rp->count--; rp->state = 'W'; } pcb *p = head; if(head->next==NULL&&head1->next==NULL) return; printf("----------處於就緒對列的程序----------\n"); // 輸出就緒的佇列 while(p->next!=NULL) { display(p->next); p = p->next; } pcb *q = head1; while(q->next!=NULL) { display(q->next); q = q->next; } sort(); } int main() { create();// 創造程序 pcb * p; while(head->next!=NULL || head1->next!=NULL) // 判斷兩個對列的程序是否都走完 { if(head->next!=NULL) { p= head->next; p->state='R'; runpcb(p); } else { arrivetime(); } } return 0; }