模擬實現作業系統排程演算法
之前學習作業系統的時候對作業系統的一些排程演算法比較感興趣,所以自己模擬實現了一下作業系統演算法的排程,我主要模擬實現了短作業優先和先來先服務排程演算法。程式碼有點長,加上測試程式碼估計有300行左右吧,放在這裡的話看起來也不方便(算了,還是放在下面吧,免得看的人覺得麻煩)。我先把實現的結果截圖放在下面吧,然後再附上程式碼,其實在我的github上面也有這些程式碼的,地址: https://github.com/admin-zou/DS/tree/master/scheduling
標頭檔案: //scheduling.h
#ifndef _SCHEDULING_ #define _SCHEDULING_ #include <iostream> #include <stdlib.h> using namespace std; enum Tag{UNSHD,SHD}; //標記是否被排程過 struct PCB { int pcbid; //程序號 size_t arrtime; //到達時間 size_t sertime; //服務時間 size_t begtime; //開始時間 size_t endtime; //完成時間 size_t turntime; //週轉時間 float weighttime; //帶權週轉時間 PCB * next; //指向下個節點的指標 Tag tag; //標記是否被排程過 PCB(int n=0,size_t a=0,size_t s=0) :pcbid(n),arrtime(a),sertime(s),begtime(0),endtime(0) ,turntime(0),weighttime(0),next(NULL),tag(UNSHD) {} }; class scheduling { public: scheduling():_curtime(0),_tasknum(0) { _head = new PCB(); } /////先來先服務演算法 void FIFS() { if(empty()) { cout<<"沒有任務"; exit(-1); } _clear(); //清理一下,可重複計算 _sort_t(); //按到達時間排序 PCB* cur = _head->next; while(NULL != cur) { if(_curtime < cur->arrtime) { _curtime = cur->arrtime; } cur->begtime = _curtime; cur->endtime = _curtime + cur->sertime; //完成時間等於開始時間加服務時間 cur->turntime = cur->endtime - cur->arrtime; //週轉時間=完成時間-到達時間 cur->weighttime = (float)cur->turntime / (float)cur->sertime; //帶權週轉時間=週轉時間/服務時間 cur->tag = SHD; //標記為已經服務 _curtime += cur->sertime; cur = cur->next; } } /////短作業 void Short() { if (empty()) { cout << "沒有任務"; exit(-1); } _clear(); //清理一下,可重複計算 _sort_t(); //按到達時間排序 PCB* cur = _head->next; while (NULL != cur) { if (_curtime < cur->arrtime) { _curtime = cur->arrtime; } cur->begtime = _curtime; cur->endtime = _curtime + cur->sertime; //完成時間等於開始時間加服務時間 cur->turntime = cur->endtime - cur->arrtime; //週轉時間=完成時間-到達時間 cur->weighttime = (float)cur->turntime / (float)cur->sertime; //帶權週轉時間=週轉時間/服務時間 cur->tag = SHD; //標記為已經服務 _curtime += cur->sertime; cur = cur->next; //將該程序排程完的時刻已經到達的程序按短作業優先排序 _sort_l(cur,_curtime); //從該程序開始進行短作業排序 } } void Init_task() { int tasknum=0; size_t id=0; size_t atime=0; size_t stime=0; cout<<"請輸入任務的個數:"; cin>>tasknum; for(int i = 0; i<tasknum;i++) { cout<<"請分別輸入任務的編號,到達時間,執行時間:"; cin>>id>>atime>>stime; push(id,atime,stime); } } void Push() { size_t id=0; size_t atime=0; size_t stime=0; cout<<"請分別輸入任務的編號,到達時間,執行時間:"; cin>>id>>atime>>stime; push(id,atime,stime); } void Print() { if(empty()) return ; PCB* cur = _head->next; printf("程序號 到達時間 服務時間 開始時間 完成時間 週轉時間 帶權週轉時間 \n"); while(NULL != cur) { printf("%4d %6d %8d %9d %7d %8d\t %0.2f\n",cur->pcbid, cur->arrtime ,cur->sertime ,cur->begtime, cur->endtime ,cur->turntime ,cur->weighttime); cur = cur->next; } } protected: bool empty() { return _tasknum == 0; } bool push(int n,size_t a,size_t s) //插入到連結串列尾部 { PCB * newtask = new PCB(n,a,s); PCB * cur = _head; while(NULL != cur->next) cur =cur->next; cur->next=newtask; _tasknum++; return true; } void _clear() { if(empty()) return ; PCB* cur = _head->next; while(NULL != cur) { cur->begtime = 0; cur->endtime = 0; cur->turntime = 0; cur->weighttime = 0; cur->tag = UNSHD; cur = cur->next ; } _curtime = 0; } // 按照到達時間排序 void _sort_t() { if(empty() || _tasknum == 1) return; PCB* prev = _head->next; PCB* cur = prev->next; for(int i = 0; i< _tasknum-1; i++) { for(int j = 0; j<_tasknum-i-1; j++) { if (prev->arrtime > cur->arrtime) { _Swap(prev, cur); } prev = cur; cur = cur->next; } prev=_head->next; cur = prev->next; } } // 按照作業長短排序 void _sort_l(PCB*& head,size_t curtime) { if (NULL == head || NULL == head->next) return; PCB* prev = head; PCB* cur = prev->next; int size = 0; //計算程序的數目 PCB* tmp = head; while (tmp) { ++size; tmp = tmp->next; } for (int i = 0; cur->arrtime < curtime && i < size - 1; i++) { if (prev->arrtime > curtime) {//作業還沒到達就不排序 return; } for (int j = 0; j < size - i - 1; j++) { if (cur && cur->arrtime <= curtime) { int ptime = prev->sertime; int ctime = cur->sertime; if (ptime > ctime) { _Swap(prev, cur); } } prev = cur; cur = cur->next; } prev = head; cur = prev->next; } } void _Swap(PCB * prev,PCB * cur) { swap(prev->arrtime,cur->arrtime); swap(prev->pcbid ,cur->pcbid ); swap(prev->sertime ,cur->sertime ); } private: PCB * _head; size_t _curtime; size_t _tasknum; //作業個數 }; #endif
測試檔案:
#define _CRT_NOWANRINGS #include"scheduling.h" int main() { int select=1; scheduling mytask; while(select) { cout<<"****************************"<<endl; cout<<"* 1.初始化 *"<<endl; cout<<"* 2.新插入一個程序 *"<<endl; cout<<"* 3.先來先服務排程演算法 *"<<endl; cout<<"* 4.短作業排程演算法 *"<<endl; cout<<"* 5.顯示排程情況 *"<<endl; cout<<"* 0.退出 *"<<endl; cout<<"****************************"<<endl; int item=0; cout<<"請輸入:"; cin>>select; switch(select) { case 1: mytask.Init_task(); break; case 2: mytask.Push(); break; case 3: mytask.FIFS(); break; case 4: mytask.Short(); break; case 5: mytask.Print(); cout << endl; break; default: break; } } return 0; } //測試條件 /* 5 1 0 4 2 2 4 3 3 3 4 5 6 5 6 3 */
總結:
1.上面的程式基於是我對作業系統排程演算法的理解所寫出來的,主要模擬了先來先服務和短作業優先排程兩種排程演算法,其中涉及到了c++,資料結構以及作業系統和演算法等方面的只是,實現它確實大有所益。
2.在上面的小專案中我是通過計算出各種排程演算法的週轉時間,帶權週轉時間等等來評價排程演算法的效率的,能夠在一定範圍內評估排程演算法的效能,以及某些場景適合於使用哪種排程演算法。
3.我是通過單鏈表來組織相關的作業的排程需要的資料的,這樣確實有好處,也有缺陷,這和連結串列的優缺點相對應。不過在資料量較小的時候還是很不錯的。
其中主要的難點在於很難分析出所有可能出現的情況,以及各種情況下的行為。還有就是,需要對作業系統的排程演算法有一定的理解,否則就容易出現於實際不符的結果,比如說短作業優先排程,怎樣理解這種排程方式呢,我舉個例子吧:一開始時只有一個作業在排程,但是其所需時間比較長,在他執行過程中來了其他作業,但是作業時間很短,先排程這個短作業可能會更優,那麼我們需要怎麼處理呢,這就涉及到了是否允許搶佔資源的問題(當然在我的實現中是不可搶佔資源的)。最後說明一下在開發的時候一定要多除錯,減少bug,增加程式的健壯性。