進程式控制制 基本要求 模擬操作系統內核對進程的控制和管理:包括進程的創建和撤銷、進程狀態的切換和簡單的記憶體空間管理。 實驗提示 1、 定義管理每個進程的數據結構PCB:包含進程名稱、隊列指針、分配的物理記憶體區域(基址和長度)。每創建一個進程時,需要為其創建PCB並分配空閑記憶體空間,對PCB進行初始化, ...
進程式控制制
基本要求
模擬操作系統內核對進程的控制和管理:包括進程的創建和撤銷、進程狀態的切換和簡單的記憶體空間管理。
實驗提示
1、 定義管理每個進程的數據結構PCB:包含進程名稱、隊列指針、分配的物理記憶體區域(基址和長度)。每創建一個進程時,需要為其創建PCB並分配空閑記憶體空間,對PCB進行初始化,並加入就緒隊列。(斜體為可選)
可參考如下數據結構(動態形式):
struct PCB{ char name[8]; struct PCB *next; ... }; struct PCB *ready,*blocked,*running; |
創建進程時申請空白PCB:
struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB)); |
並把新建進程的PCB添加到就緒隊列末尾:
add(ready,p); |
其中,ready為就緒隊列頭節點,併在開始處分配了空間;add函數是鏈表中添加節點函數,代碼參考如下:
void add(struct PCB *head, struct PCB *process){ struct PCB *tmp=head; while(tmp->next!=NULL) tmp=tmp->next; tmp->next=process; process->next=NULL; }
2、 模擬觸發進程狀態轉換的事件:採用鍵盤控制方法來模擬觸發進程狀態切換的事件(例如輸入1代表創建新進程、2執行進程時間片到、3阻塞執行進程、4喚醒第一個阻塞進程、5終止執行進程),實現對應的控製程序。
3、 根據當前發生的事件對進程的狀態進行切換,並顯示出當前系統中的執行隊列、就緒隊列和阻塞隊列。
4、 *(選做)完成可變分區的分配與回收,創建進程的同時申請一塊連續的記憶體空間,在PCB中設置好基址和長度,結束進程時回收分配的記憶體空間。分配可採用首次適應、最佳適應或最差適應演算法,碎片大小為2Kb,最後回收所有進程的空間,對空間分區的合併。可以查看進程所占的空間和系統空閑空間。
可以用一個鏈表(如圖1-1所示)來維護已分配的和空閑的記憶體段,其中一個段或者包含一個進程,或者是兩個進程之間的空閑段。 在圖1-1中,鏈表的每一項包含四個值域。第一個值域表示記憶體段是空閑或占用(例如,空閑段用H表示,進程占用的段用P表示);第二個值域表示記憶體段的起始位置,第三個值域表示記憶體段的長度;第四個值域為指向鏈表下一項的指針。該鏈表按照記憶體段的起始地址進行從小到大排序。這樣排序的好處是方便記憶體空間的回收。一個要終止的進程一般會有兩個鄰居(除了在記憶體頂端和記憶體底端的進程)。鄰居可能是進程也可能是空閑段。根據兩個鄰居的不同類型,可以分為四種回收情況(如圖1-2所示)。在圖1-2(a)中,對鏈表的更新只需要將P置為H;在圖1-2(b)和(c)中,需要將P置為H,並將該項與另外一個相鄰的空閑段的項合併為一項;在圖1-2(d)中,需要將該項和兩個鄰居合併為一項。考慮到合併空閑段需要查看鄰居,因此用雙向鏈表會比單向鏈表更加方便。
圖 1-1. (a) 記憶體空間的示例,有5個進程和3個空閑段,陰影部分表示空閑段。
(b) 管理記憶體空間的鏈表
圖 1-2. 對終止的進程X的四種記憶體回收情況(陰影代表空閑區)
實驗代碼
#include<iostream> #include<stdlib.h> #include<string.h> using namespace std; struct PCB{ char name[8]; struct PCB *next; }; struct PCB *ready,*blocked,*running; struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB)); //插入隊列 void add(struct PCB *head,struct PCB *process){ struct PCB *tmp=head; while(tmp->next!=NULL) tmp=tmp->next; tmp->next=process; process->next=NULL; } //出隊列 struct PCB *movefirst(struct PCB *head){ struct PCB *tmp=head->next; if(tmp!=NULL) { head->next=tmp->next; tmp->next=NULL; } return tmp; }; //創建進程 void creat() { struct PCB *tmp; char name[10]; cout<<"輸入進程名字:"; cin>>name; tmp=(struct PCB*)malloc(sizeof(struct PCB)); strcpy(tmp->name,name); //字元串複製函數 tmp->next=NULL; add(ready,tmp); if(running==NULL) //如果當前沒有正在執行的進程就將新創建的進程運行 running=movefirst(ready); } //時間片到 void timeout(){ if(ready->next==NULL) // 容錯處理 cout<<"\t\t就緒隊列為空!"<<endl; if(running!=NULL) { add(ready,running); running=movefirst(ready); } else running=movefirst(ready); } //阻塞進程 void block(){ if(running!=NULL) { add(blocked,running); running=movefirst(ready); } else cout<<"\t\t沒有運行的進程,無法阻塞!"<<endl; } //喚醒進程 void wakeup(){ if (blocked->next == NULL){ printf("阻塞態已為空!!!\n"); } else{ struct PCB *T = (struct PCB*)malloc(sizeof(struct PCB)); T = movefirst(blocked); add(ready,T); if (running == NULL){ running =movefirst(ready); } } } //終止進程 void stop(){ if(running!=NULL) { free(running); running=movefirst(ready); } else cout<<"\t\t沒有運行的進程"<<endl; } //展示 void show() { struct PCB *tmp; cout<<endl; cout<<"執行隊列:"; if(running!=NULL) cout<<" "<<running->name; cout<<endl; cout<<"就緒隊列:"; tmp=ready->next; while(tmp!=NULL){ cout<<" "<<tmp->name; tmp=tmp->next; } cout<<endl; cout<<"阻塞隊列:"; tmp=blocked->next; while(tmp!=NULL){ cout<<" "<<tmp->name; tmp=tmp->next; } cout<<endl; cout<<endl; } //菜單 void menu() { cout<<"\t\t--------------------"<<endl; cout<<"\t\t1.創建進程"<<endl; cout<<"\t\t2.時間片到"<<endl; cout<<"\t\t3.阻塞進程"<<endl; cout<<"\t\t4.喚醒進程"<<endl;; cout<<"\t\t5.終止進程"<<endl; cout<<"\t\t6.退出程式"<<endl; cout<<"\t\t--------------------"<<endl; } main() { ready=(struct PCB*)malloc(sizeof(struct PCB)); ready->next=NULL; blocked=(struct PCB*)malloc(sizeof(struct PCB)); blocked->next=NULL; int c; while(1) { menu(); cout<<"輸入功能:"; cin>>c; switch(c) { case 1: creat(); break; case 2: timeout(); break; case 3: block(); break; case 4: wakeup(); break; case 5: stop(); break; case 6: exit(0); default: cout<<"沒有這個選項,請重新輸入"<<endl; } show(); } }