C++ 搶佔時優先順序程序排程
阿新 • • 發佈:2021-06-30
- 先來先服務
- 短程序優先演算法
- 優先順序排程(搶佔)
- 優先順序排程
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> using namespace std; struct PCB { int id; // 程序id double turnaround_time; // 週轉時間 double weighted_turnaround_time; // 帶權週轉時間 double wait_time; // 等待時間 double start_time; // 開始時間 double coming_time; // 到達時間 double service_time; // 執行時間 double finish_time; // 完成時間 int youxianji; // 優先順序 double run_time; // 已執行時間 }; int n; // 程序個數 vector<PCB> process_list; // 輸入的程序序列 vector<PCB> res; // 待輸出的結果佇列 void input_process_count() { printf("請輸入程序數量:"); scanf("%d", &n); for (int i = 0; i < n; i++) { PCB pcb; // pcb初始化 pcb.id = i + 1; pcb.run_time = 0; // 初始時已執行時間為零 pcb.start_time = -1; // 為判斷是否第一次到達 process_list.push_back(pcb); // 加入已初始化好的pcb } } void input_youxianshu() // 輸入優先順序 { for (int i = 0; i < n; i++) { printf("請輸入程序%d的優先順序:", process_list[i].id); scanf("%d", &process_list[i].youxianji); } } void input_coming_time() // 輸入到達時間 { for (int i = 0; i < n; i++) { printf("請輸入程序%d的到達時間:", process_list[i].id); scanf("%lf", &process_list[i].coming_time); } } void input_serve_time() // 輸入需要服務時間 { for (int i = 0; i < n; i++) { printf("請輸入程序%d所需時間", process_list[i].id); scanf("%lf", &process_list[i].service_time); } } int choose_method() // 輸入選擇的演算法 { int select = 0; cout << "*****************************************\n"; cout << "1 \t 先來先服務演算法 *******\n"; cout << "2 \t 短程序優先演算法 *******\n"; cout << "3 \t 優先順序排程(搶佔) *******\n"; cout << "4 \t 優先順序排程(非搶佔) *******\n"; cout << "請選擇: "; cin >> select; return select; } int cmpByComingTime(PCB a, PCB b) // 按照到達時間從小到大排序 { return a.coming_time < b.coming_time; } int cmpByServiceTime(PCB a, PCB b) // 按照需要服務時間從大到小排序 { return a.service_time > b.service_time; } void FCFS() { sort(process_list.begin(), process_list.end(), cmpByComingTime); // 先按照到達時間排序 double time = process_list[0].coming_time; // 初始化時間 for (int i = 0; i < n; i++) { PCB pcb = process_list[i]; // 因為已經按照時間排序,所以當前為待執行的程序 // 更新當前程序的資訊 pcb.start_time = time; pcb.wait_time = time - pcb.coming_time; pcb.finish_time = time + pcb.service_time; pcb.turnaround_time = pcb.finish_time - pcb.coming_time; pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time; time = pcb.finish_time; // 以當前程序的時間更新time process_list[i] = pcb; res.push_back(pcb); // 加入結果佇列 } } void SJF() { int top = 0; vector<PCB> short_jobs; // 定義短程序佇列 其中資料由大到小 sort(process_list.begin(), process_list.end(), cmpByComingTime); // 按照到達時間初始化 double time = process_list[0].coming_time; // 初始化時間 while (top < n || !short_jobs.empty()) // 如果兩個對列裡仍然存在元素 { if (short_jobs.empty()) // 如果佇列未空,則加入當前已經到達的程序 short_jobs.push_back(process_list[top++]); PCB pcb = short_jobs[int(short_jobs.size() - 1)]; // 取出時間最短的 if (pcb.start_time == -1) pcb.start_time = time; // 更新pcb的時間 pcb.wait_time = time - pcb.coming_time; pcb.finish_time = time + pcb.service_time; pcb.turnaround_time = pcb.finish_time - pcb.coming_time; pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time; time = pcb.finish_time; // 加入到執行結束佇列 res.push_back(pcb); short_jobs.pop_back(); // 如果在上個程序執行期間有程序到達則加入short_jobs佇列 for (; top < n && process_list[top].coming_time < time; top++) { short_jobs.push_back(process_list[top]); } // 因為有新的程序加入,所以對short_jobs進行排序 sort(short_jobs.begin(), short_jobs.end(), cmpByComingTime); } } bool cmpByPriority(PCB a, PCB b) // 按照優先順序排序 { if (a.youxianji == b.youxianji) return a.coming_time > b.coming_time; return a.youxianji < b.youxianji; } void PriorityNo() // 非搶佔優先順序排程 { int top = 0; // 定義頭指標 vector<PCB> priority_higher; sort(process_list.begin(), process_list.end(), cmpByComingTime); double time = process_list[0].coming_time; while (top < n || !priority_higher.empty()) // 如果仍有程序未執行結束 { if (priority_higher.empty()) // 為空則加入新的程序 priority_higher.push_back(process_list[top++]); PCB pcb = priority_higher[int(priority_higher.size() - 1)]; // 取出要執行的程序 if (pcb.start_time == -1) //如果是第一次抵達則更新時間 pcb.start_time = time; // 更新pcb pcb.wait_time = time - pcb.coming_time; pcb.finish_time = time + pcb.service_time; pcb.turnaround_time = pcb.finish_time - pcb.coming_time; pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time; time = pcb.finish_time; res.push_back(pcb); // 執行結束則加入res priority_higher.pop_back(); // 並刪除已執行結束的程序 for (; top < n && process_list[top].coming_time < time; top++) { // 加入在此期間到達的程序 priority_higher.push_back(process_list[top]); } // 因為有新程序加入,進行排序 sort(priority_higher.begin(), priority_higher.end(), cmpByPriority); } } void PriorityYes() { int top = 0; vector<PCB> priority_higher; sort(process_list.begin(), process_list.end(), cmpByComingTime); double time = process_list[0].coming_time; // 初始化時間 while (top < n || !priority_higher.empty()) // 如果仍有程序未結束 { if (priority_higher.empty()) // 如果為空,則加入新的程序 priority_higher.push_back(process_list[top++]); PCB pcb = priority_higher[int(priority_higher.size() - 1)]; // 取出優先順序最高的程序執行 if (pcb.start_time == -1) // 如果是第一次到達,則記錄開始時間 { pcb.start_time = time; pcb.wait_time = pcb.start_time - pcb.coming_time; } if (top < n && process_list[top].coming_time <= time + pcb.service_time - pcb.run_time) // 如果仍有未加入的程序, 並且在執行期間有新的程序到達 { pcb.run_time += process_list[top].coming_time - time; // 則先執行距離下個程序到達的時間 time += process_list[top].coming_time - time; // 並更新時間 priority_higher[priority_higher.size() - 1] = pcb; // 更新佇列 priority_higher.push_back(process_list[top++]); // 把下一個程序加入 sort(priority_higher.begin(), priority_higher.end(), cmpByPriority); // 並進行排序 if (pcb.run_time == pcb.service_time) // 如果當前程序的執行時間已經夠了,則更新pcb資訊,並刪除程序 { pcb.finish_time = time; pcb.turnaround_time = pcb.finish_time - pcb.coming_time; pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time; res.push_back(pcb); priority_higher.pop_back(); } } else // 如果沒有新的程序到達, 則將當前程序執行完畢 { pcb.finish_time = time + pcb.service_time - pcb.run_time; pcb.turnaround_time = pcb.finish_time - pcb.coming_time; pcb.weighted_turnaround_time = (pcb.turnaround_time) / pcb.service_time; time = time + pcb.service_time - pcb.run_time; res.push_back(pcb); // 執行完畢則加入res priority_higher.pop_back(); } } } bool cmpById(PCB a, PCB b) { return a.id < b.id; } void print_schedulInfo() { printf("程序編號\t提交時間\t執行時間\t開始時間\t等待時間\t完成時間\t週轉時間\t帶權週轉時間\n"); // cout << res.size() << endl; sort(res.begin(), res.end(), cmpById); // 按照ID排序 double start = 0x3f3f3f3f3f, end = 0; double allTT = 0, allWTT = 0, runTime = 0; for (int i = 0; i < n; i++) { PCB pcb = res[i]; start = min(start, pcb.start_time); // 得到開始時間 end = max(end, pcb.finish_time); // 所有程序結束時間 allTT += pcb.turnaround_time; // 總的週轉時間 allWTT += pcb.weighted_turnaround_time; // 總的帶權週轉時間 runTime += pcb.service_time; // 總的服務時間 printf("%8d\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n", pcb.id, pcb.coming_time, pcb.service_time, pcb.start_time, pcb.wait_time, pcb.finish_time, pcb.turnaround_time, pcb.weighted_turnaround_time); } printf("平均週轉時間%.2f\t平均帶權週轉時間%.2f\tCPU利用率%.2f\t系統吞吐量%.2f\n", allTT / n, allWTT / n, (runTime) / (end - start), (n) / (end - start)); } int main() { // 4 1 1 1 1 9 8 8.4 8.8 0.2 2 1 0.5 // 4 2 4 3 1 10 20 30 50 20 30 25 20 // 4 1 2 3 2 0 2 4 5 7 4 1 4 input_process_count(); // 輸出程序數量 input_youxianshu(); // 輸入優先順序數 input_coming_time(); // 輸入到達時間 input_serve_time(); // 輸入需要服務時間 int choose = choose_method(); // 得到使用者選擇的數 // printf("%d\n", choose); switch (choose) { case 1: FCFS(); // 先來先服務 break; case 2: SJF(); // 短作業優先 break; case 3: PriorityYes(); // 優先順序搶佔式 break; default: PriorityNo(); // 優先順序非搶佔式 break; } print_schedulInfo(); // 列印結果 return 0; }