日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

操作系统实验报告16:CPU 调度

發(fā)布時(shí)間:2024/6/3 windows 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 操作系统实验报告16:CPU 调度 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

操作系統(tǒng)實(shí)驗(yàn)報(bào)告16

實(shí)驗(yàn)內(nèi)容

  • 實(shí)驗(yàn)內(nèi)容:CPU 調(diào)度。
    • 討論課件 Lecture19-20 中 CPU 調(diào)度算法的例子,嘗試基于 POSIX API 設(shè)計(jì)一個(gè)簡(jiǎn)單調(diào)度器(不考慮資源競(jìng)爭(zhēng)問(wèn)題):
      • 創(chuàng)建一些 Pthread 線程任務(wù),建立一個(gè)管理鏈隊(duì)列,結(jié)點(diǎn)內(nèi)容起碼包括到達(dá)時(shí)間、WCT、優(yōu)先級(jí)、調(diào)度狀態(tài)(運(yùn)行、就緒、阻塞)等調(diào)度參數(shù);
      • 每個(gè)任務(wù)有一個(gè)調(diào)度信號(hào)量,任務(wù)啟動(dòng)后在其調(diào)度信號(hào)量上執(zhí)行 wait;
      • 調(diào)度器按照調(diào)度策略對(duì)處于運(yùn)行態(tài)的任務(wù)(如果有的話)的調(diào)度信號(hào)量執(zhí)行 wait,并選取適當(dāng)任務(wù)的調(diào)度信號(hào)量執(zhí)行 signal;
      • 實(shí)現(xiàn)簡(jiǎn)單調(diào)度策略:FCFS、SJF、Priority。分別計(jì)算任務(wù)平均等待時(shí)間。
    • 拓展問(wèn)題1:設(shè)計(jì)若干資源信號(hào)量模擬資源競(jìng)爭(zhēng)情況;增加時(shí)間片參數(shù)實(shí)現(xiàn) RR 調(diào)度;驗(yàn)證優(yōu)先級(jí)反轉(zhuǎn);建立多個(gè)鏈隊(duì)列實(shí)現(xiàn)多級(jí)反饋調(diào)度。
    • 拓展問(wèn)題2:設(shè)計(jì)一個(gè)搶占式優(yōu)先策略實(shí)時(shí)調(diào)度器,測(cè)試在一個(gè)給定的工作負(fù)載下優(yōu)先級(jí)反轉(zhuǎn)的情況。

實(shí)驗(yàn)環(huán)境

  • 架構(gòu):Intel x86_64 (虛擬機(jī))
  • 操作系統(tǒng):Ubuntu 20.04
  • 匯編器:gas (GNU Assembler) in AT&T mode
  • 編譯器:gcc

技術(shù)日志

實(shí)驗(yàn)內(nèi)容原理

  • CPU調(diào)度程序
    • 每當(dāng)CPU空閑時(shí),操作系統(tǒng)就應(yīng)從就緒隊(duì)列中選擇一個(gè)進(jìn)程來(lái)執(zhí)行。進(jìn)程執(zhí)行選擇短期調(diào)度程序或CPU調(diào)度程序。調(diào)度程序從內(nèi)存中選擇一個(gè)能夠執(zhí)行的進(jìn)程,并為其分配CPU。
    • 注意,就緒隊(duì)列不必是先進(jìn)先出隊(duì)列。就緒隊(duì)列的實(shí)現(xiàn)可以是FIFO隊(duì)列、優(yōu)先隊(duì)列、樹(shù)或簡(jiǎn)單的無(wú)序鏈表等。然而,在概念上,就緒隊(duì)列內(nèi)的所有進(jìn)程都要排隊(duì)以便等待在CPU上運(yùn)行。隊(duì)列內(nèi)的記錄通常為進(jìn)程控制塊(PCB)。
  • 搶占調(diào)度
    • 需進(jìn)行CPU調(diào)度的情況可分為以下四種:
      • 當(dāng)一個(gè)進(jìn)程從運(yùn)行狀態(tài)切換到等待狀態(tài)時(shí)(例如,I/O請(qǐng)求,或wait()調(diào)用以便等待一個(gè)子進(jìn)程的終止)。
      • 當(dāng)一個(gè)進(jìn)程從運(yùn)行狀態(tài)切換到就緒狀態(tài)時(shí)(例如,當(dāng)出現(xiàn)中斷時(shí))。
      • 當(dāng)一個(gè)進(jìn)程從等待狀態(tài)切換到就緒狀態(tài)時(shí)(例如,I/O完成)。
      • 當(dāng)一個(gè)進(jìn)程終止時(shí)。
    • 對(duì)于第1種和第4種情況,除了調(diào)度沒(méi)有選擇。一個(gè)新進(jìn)程(如果就緒隊(duì)列有一個(gè)進(jìn)程存在)必須被選擇執(zhí)行。不過(guò),對(duì)于第2種和第3種情況,還是有選擇的。
    • 如果調(diào)度只能發(fā)生在第1種和第4種情況下,則調(diào)度方案稱為非搶占的或協(xié)作的;否則,調(diào)度方案稱為搶占的。
      • 在非搶占調(diào)度下,一旦某個(gè)進(jìn)程分配到CPU,該進(jìn)程就會(huì)一直使用CPU,直到它終止或切換到等待狀態(tài)。
    • 當(dāng)多個(gè)進(jìn)程共享數(shù)據(jù)時(shí),搶占調(diào)度可能導(dǎo)致競(jìng)爭(zhēng)情況。
  • 調(diào)度算法
    • 先到先服務(wù)(FCFS)調(diào)度
      • 是非搶占式算法
      • 采用這種方案,先請(qǐng)求CPU的進(jìn)程首先分配到CPU。
      • FCFS策略可以通過(guò)FIFO隊(duì)列容易地實(shí)現(xiàn)。當(dāng)一個(gè)進(jìn)程進(jìn)入就緒隊(duì)列時(shí),它的PCB會(huì)被鏈接到隊(duì)列尾部。當(dāng)CPU空閑時(shí),它會(huì)分配給位于隊(duì)列頭部的進(jìn)程,并且這個(gè)運(yùn)行進(jìn)程從隊(duì)列中移去。
      • FCFS調(diào)度代碼編寫簡(jiǎn)單并且理解容易。缺點(diǎn)是,平均等待時(shí)間往往很長(zhǎng)。
      • 護(hù)航效果:所有其他進(jìn)程都等待一個(gè)大進(jìn)程釋放CPU。與讓較短進(jìn)程先進(jìn)行相比,這會(huì)導(dǎo)致CPU和設(shè)備的使用率降低。
    • 最短作業(yè)優(yōu)先(SJF)調(diào)度
      • 有非搶占式也有搶占式算法
      • 這個(gè)算法將每個(gè)進(jìn)程與其下次CPU執(zhí)行的長(zhǎng)度關(guān)聯(lián)起來(lái)。當(dāng)CPU變?yōu)榭臻e時(shí),它會(huì)被賦給具有最短CPU執(zhí)行的進(jìn)程。如果兩個(gè)進(jìn)程具有同樣長(zhǎng)度的CPU執(zhí)行,那么可以由FCFS來(lái)處理。
      • 注意,一個(gè)更為恰當(dāng)?shù)谋硎臼亲疃滔麓蜟PU執(zhí)行算法,這是因?yàn)檎{(diào)度取決于進(jìn)程的下次CPU執(zhí)行的長(zhǎng)度,而不是其總的長(zhǎng)度。
      • 當(dāng)一個(gè)新進(jìn)程到達(dá)就緒隊(duì)列而以前進(jìn)程正在執(zhí)行時(shí),就需要選擇使用非搶占式算法還是搶占式算法了。新進(jìn)程的下次CPU執(zhí)行,與當(dāng)前運(yùn)行進(jìn)程的尚未完成的CPU執(zhí)行相比,可能還要小。
        • 搶占SJF算法會(huì)搶占當(dāng)前運(yùn)行進(jìn)程。
        • 非搶占SJF算法會(huì)允許當(dāng)前運(yùn)行進(jìn)程以先完成CPU執(zhí)行。
      • 搶占SJF調(diào)度有時(shí)稱為最短剩余時(shí)間優(yōu)先調(diào)度
    • 優(yōu)先級(jí)調(diào)度(Priority)
      • 有非搶占式也有搶占式算法
      • 每個(gè)進(jìn)程都有優(yōu)先級(jí)與其關(guān)聯(lián),而具有最高優(yōu)先級(jí)的進(jìn)程會(huì)分配到CPU。具有相同優(yōu)先級(jí)的進(jìn)程按FCFS順序調(diào)度。
      • 當(dāng)一個(gè)進(jìn)程到達(dá)就緒隊(duì)列時(shí),比較它的優(yōu)先級(jí)與當(dāng)前運(yùn)行進(jìn)程的優(yōu)先級(jí)。如果新到達(dá)進(jìn)程的優(yōu)先級(jí)高于當(dāng)前運(yùn)行進(jìn)程的優(yōu)先級(jí),那么搶占優(yōu)先級(jí)調(diào)度算法就會(huì)搶占CPU。非搶占式優(yōu)先級(jí)調(diào)度算法只是將新的進(jìn)程加到就緒隊(duì)列的頭部。
      • 優(yōu)先級(jí)調(diào)度算法的一個(gè)主要問(wèn)題是無(wú)窮阻塞或饑餓。就緒運(yùn)行但是等待CPU的進(jìn)程可以認(rèn)為是阻塞的。優(yōu)先級(jí)調(diào)度算法可讓某個(gè)低優(yōu)先級(jí)進(jìn)程無(wú)窮等待CPU。
      • 低優(yōu)先級(jí)進(jìn)程的無(wú)窮等待問(wèn)題的解決方案之一是老化。老化逐漸增加在系統(tǒng)中等待很長(zhǎng)時(shí)間的進(jìn)程的優(yōu)先級(jí)。

設(shè)計(jì)報(bào)告

調(diào)度器設(shè)計(jì)圖

代碼設(shè)計(jì)

// scheduler.c文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <pthread.h> #include <semaphore.h> #include <signal.h>#define STATUS_RUNNING 1 // 運(yùn)行調(diào)度狀態(tài) #define STATUS_READY 2 // 就緒調(diào)度狀態(tài) #define STATUS_WAITING 3 // 阻塞調(diào)度狀態(tài)#define POLICY_FCFS 1 // 先到先服務(wù)調(diào)度策略 #define POLICY_SJF_PEM 2 // 搶占式最短作業(yè)優(yōu)先調(diào)度策略 #define POLICY_SJF_NOT_PEM 3 // 非搶占式最短作業(yè)優(yōu)先調(diào)度策略 #define POLICY_PRIORITY_PEM 4 // 搶占式優(yōu)先級(jí)調(diào)度策略 #define POLICY_PRIORITY_NOT_PEM 5 // 非搶占式優(yōu)先級(jí)調(diào)度策略#define MAX_TASK_NUM 100 // 最大任務(wù)個(gè)數(shù)typedef struct node {int arrival_time; // 到達(dá)時(shí)間int WCT; // 最壞預(yù)期執(zhí)行時(shí)間int priority; // 優(yōu)先級(jí)int schedule_status; // 調(diào)度狀態(tài)pthread_t ptid; // 線程號(hào)sem_t wait_sem; // 任務(wù)啟動(dòng)時(shí)的調(diào)度等待信號(hào)量struct node *next; // 指向下一個(gè)結(jié)點(diǎn)的指針 } Tasknode; // 管理鏈隊(duì)列結(jié)點(diǎn)結(jié)構(gòu)typedef struct {Tasknode *head; // 管理鏈隊(duì)列表頭pthread_t sched_ptid; // 調(diào)度器線程的線程號(hào)pthread_mutex_t sched_mutex; // 調(diào)度器互斥鎖int schedule_policy; // 調(diào)度策略int finished_task; // 完成任務(wù)的個(gè)數(shù) } Scheduler; // 調(diào)度器結(jié)構(gòu)Scheduler sched; // 調(diào)度器 sigset_t zeromask; // 阻塞線程函數(shù)sigsuspend()所用參數(shù) long wait_sum_time = 0; // 單個(gè)線程等待總時(shí)間long begin_us, run_us; // 總計(jì)時(shí)器部分,測(cè)試用 struct timeval t_time;// 初始化調(diào)度器 void init_scheduler(int task_num); // 創(chuàng)建任務(wù)管理信息結(jié)點(diǎn) Tasknode* creat_thread_node(int arrival_time, int WCT, int priority);// 每個(gè)線程執(zhí)行的任務(wù) void *task_runner(void *arg); // 調(diào)度器運(yùn)行線程 void *schedule_runner(void *arg);// 將任務(wù)信息結(jié)點(diǎn)按照調(diào)度策略放入管理鏈隊(duì)列 void fcfs(Tasknode *new_node); void sjf_pem(Tasknode *new_node); void sjf_not_pem(Tasknode *new_node); void priority_pem(Tasknode *new_node); void priority_not_pem(Tasknode *new_node);// 向管理鏈隊(duì)列添加任務(wù) void add_task(Tasknode *node, int sched_policy); // 從管理鏈隊(duì)列刪除任務(wù) void delete_task();// 發(fā)送信號(hào)阻塞線程,直到接收到一個(gè)新的信號(hào) void thread_wait_sighand(int signo); // 發(fā)送信號(hào)使阻塞線程繼續(xù)運(yùn)行 void thread_cont_sighand(int signo); // 調(diào)度器線程接收信號(hào)后調(diào)度器選擇一個(gè)任務(wù),即表頭任務(wù)運(yùn)行 void sched_run_sighand(int signo);// 打印任務(wù)信息列表,測(cè)試用 void print_tasklist(int *arrival_time, int *WCT, int *priority, int task_num); // 計(jì)算任務(wù)平均等待時(shí)間 double cal_aver_wait_time(int *arrival_time, int *WCT, int *priority, int task_num, int sched_policy);// 調(diào)度器運(yùn)行線程 void *schedule_runner(void *arg) {int task_num = *(int *)arg;// 當(dāng)完成任務(wù)個(gè)數(shù)等于總?cè)蝿?wù)個(gè)數(shù)時(shí),調(diào)度器線程退出while (sched.finished_task != 5 * task_num);pthread_exit(0); }// 創(chuàng)建任務(wù)管理信息結(jié)點(diǎn) Tasknode* creat_thread_node(int arrival_time, int WCT, int priority) {Tasknode *new_node = (Tasknode *)malloc(sizeof(Tasknode));// 設(shè)置線程的到達(dá)時(shí)間,最長(zhǎng)預(yù)期執(zhí)行時(shí)間,優(yōu)先級(jí)new_node->arrival_time = arrival_time;new_node->WCT = WCT;new_node->priority = priority;new_node->next = NULL;// 初始化線程的調(diào)度等待信號(hào)量為0int ret = sem_init(&new_node->wait_sem, 1, 0);if (ret == -1) {perror("creat_thread_node(): sem_init-wait_sem");exit(1);}return new_node; }// 初始化調(diào)度器 void init_scheduler(int task_num) {// 管理鏈隊(duì)列的表頭為空sched.head = NULL;// 調(diào)度策略默認(rèn)為先到先服務(wù)sched.schedule_policy = POLICY_FCFS;// 已經(jīng)完成任務(wù)個(gè)數(shù)為0sched.finished_task = 0;// 初始化調(diào)度器互斥鎖pthread_mutex_init(&sched.sched_mutex, NULL);// 創(chuàng)建調(diào)度器運(yùn)行線程int ret = pthread_create(&sched.sched_ptid, NULL, &schedule_runner, &task_num);if (ret != 0) {fprintf(stderr, "init_scheduler(): pthread_create error: %s\n", strerror(ret));exit(1);} }// 將任務(wù)信息結(jié)點(diǎn)按照先到先服務(wù)策略放入管理鏈隊(duì)列 void fcfs(Tasknode *new_node) {// 如果管理鏈隊(duì)列的表頭為空,那么直接插入結(jié)點(diǎn)if (sched.head == NULL) {sched.head = new_node;return;}// 找到管理鏈隊(duì)列的表尾,插入結(jié)點(diǎn)Tasknode *cur_node = sched.head;while (cur_node->next != NULL) {cur_node = cur_node->next;}cur_node->next = new_node; }// 將任務(wù)信息結(jié)點(diǎn)按照搶占式最短作業(yè)優(yōu)先策略放入管理鏈隊(duì)列 void sjf_pem(Tasknode *new_node) {// 如果管理鏈隊(duì)列的表頭為空,那么直接插入結(jié)點(diǎn)if (sched.head == NULL) {sched.head = new_node;return;}// 如果結(jié)點(diǎn)的WCT小于表頭結(jié)點(diǎn)的WCT,那么直接在表頭結(jié)點(diǎn)之前插入結(jié)點(diǎn)else if (new_node->WCT < sched.head->WCT) {new_node->next = sched.head;sched.head = new_node;return;}Tasknode *cur_node = sched.head;Tasknode *pre_node = NULL;while (cur_node != NULL && new_node->WCT >= cur_node->WCT) {pre_node = cur_node;cur_node = cur_node->next;}pre_node->next = new_node;new_node->next = cur_node; }// 將任務(wù)信息結(jié)點(diǎn)按照非搶占式最短作業(yè)優(yōu)先策略放入管理鏈隊(duì)列 void sjf_not_pem(Tasknode *new_node) {// 如果管理鏈隊(duì)列的表頭為空,那么直接插入結(jié)點(diǎn)if (sched.head == NULL) {sched.head = new_node;return;}// 尋找管理鏈隊(duì)列中前一個(gè)結(jié)點(diǎn)的WCT小于等于結(jié)點(diǎn),后一個(gè)結(jié)點(diǎn)的WCT大于結(jié)點(diǎn)的位置插入結(jié)點(diǎn),如果沒(méi)有那么就在表尾插入結(jié)點(diǎn)Tasknode *cur_node = sched.head->next;Tasknode *pre_node = sched.head;while (cur_node != NULL && new_node->WCT >= cur_node->WCT) {pre_node = cur_node;cur_node = cur_node->next;}pre_node->next = new_node;new_node->next = cur_node; }// 將任務(wù)信息結(jié)點(diǎn)按照搶占式優(yōu)先級(jí)策略放入管理鏈隊(duì)列 void priority_pem(Tasknode *new_node) {// 如果管理鏈隊(duì)列的表頭為空,那么直接插入結(jié)點(diǎn)if (sched.head == NULL) {sched.head = new_node;return;}// 如果結(jié)點(diǎn)的優(yōu)先級(jí)大于表頭結(jié)點(diǎn)的優(yōu)先級(jí),那么直接在表頭結(jié)點(diǎn)之前插入結(jié)點(diǎn)else if (new_node->priority > sched.head->priority) {new_node->next = sched.head;sched.head = new_node;return;}// 尋找管理鏈隊(duì)列中前一個(gè)結(jié)點(diǎn)的WCT小于等于結(jié)點(diǎn),后一個(gè)結(jié)點(diǎn)的WCT大于結(jié)點(diǎn)的位置插入結(jié)點(diǎn),如果沒(méi)有那么就在表尾插入結(jié)點(diǎn)Tasknode *cur_node = sched.head;Tasknode *pre_node = NULL;while (cur_node != NULL && new_node->priority <= cur_node->priority) {pre_node = cur_node;cur_node = cur_node->next;}pre_node->next = new_node;new_node->next = cur_node; }// 將任務(wù)信息結(jié)點(diǎn)按照非搶占式優(yōu)先級(jí)策略放入管理鏈隊(duì)列 void priority_not_pem(Tasknode *new_node) {// 如果管理鏈隊(duì)列的表頭為空,那么直接插入結(jié)點(diǎn)if (sched.head == NULL) {sched.head = new_node;return;}// 尋找管理鏈隊(duì)列中前一個(gè)結(jié)點(diǎn)的優(yōu)先級(jí)大于等于結(jié)點(diǎn),后一個(gè)結(jié)點(diǎn)的優(yōu)先級(jí)小于結(jié)點(diǎn)的位置插入結(jié)點(diǎn),如果沒(méi)有那么就在表尾插入結(jié)點(diǎn)Tasknode *cur_node = sched.head->next;Tasknode *pre_node = sched.head;while (cur_node != NULL && new_node->priority <= cur_node->priority) {pre_node = cur_node;cur_node = cur_node->next;}pre_node->next = new_node;new_node->next = cur_node; }// 向管理鏈隊(duì)列添加任務(wù) void add_task(Tasknode *node, int sched_policy) {// 獲取調(diào)度器的互斥鎖,防止其它線程更改調(diào)度器pthread_mutex_lock(&sched.sched_mutex);// 如果有任務(wù)正在運(yùn)行,那么先阻塞這個(gè)任務(wù),將這個(gè)任務(wù)的調(diào)度狀態(tài)改為就緒態(tài)if (sched.head != NULL) {pthread_kill(sched.head->ptid, SIGUSR1);sched.head->schedule_status = STATUS_READY;}// 添加的任務(wù)信息結(jié)點(diǎn)的調(diào)度狀態(tài)為阻塞態(tài)node->schedule_status = STATUS_WAITING;// 根據(jù)調(diào)度策略,向管理鏈隊(duì)列中插入任務(wù)信息結(jié)點(diǎn)switch (sched_policy) {case POLICY_FCFS :fcfs(node);break;case POLICY_SJF_PEM:sjf_pem(node);break;case POLICY_SJF_NOT_PEM:sjf_not_pem(node);break;case POLICY_PRIORITY_PEM:priority_pem(node);break;case POLICY_PRIORITY_NOT_PEM:priority_not_pem(node);break;}sleep(0);// 向調(diào)度器線程發(fā)送信號(hào),選取適當(dāng)?shù)娜蝿?wù)執(zhí)行pthread_kill(sched.sched_ptid, SIGUSR2);// 釋放調(diào)度器的互斥鎖pthread_mutex_unlock(&sched.sched_mutex); }// 從管理鏈隊(duì)列刪除任務(wù) void delete_task() {// 獲取調(diào)度器的互斥鎖,防止其它線程更改調(diào)度器pthread_mutex_lock(&sched.sched_mutex);// 運(yùn)行完了的任務(wù)結(jié)點(diǎn)是管理鏈隊(duì)列的頭結(jié)點(diǎn),釋放其資源Tasknode *temp = sched.head;sched.head = sched.head->next;sem_destroy(&temp->wait_sem);free(temp);temp = NULL;// 如果管理鏈隊(duì)列中還有任務(wù),那么繼續(xù)運(yùn)行if (sched.head != NULL) {pthread_kill(sched.head->ptid, SIGCONT);}// 釋放調(diào)度器的互斥鎖pthread_mutex_unlock(&sched.sched_mutex); }// 每個(gè)線程執(zhí)行的任務(wù) void *task_runner(void *arg) {int ret;// 計(jì)時(shí)器部分long start_us, end_us;struct timeval t;// 獲取每個(gè)線程的任務(wù)信息結(jié)點(diǎn)Tasknode *task_node = (Tasknode *)arg;struct timespec req, rem;// 設(shè)置這個(gè)任務(wù)信息結(jié)點(diǎn)的線程號(hào)task_node->ptid = pthread_self();// 設(shè)置線程運(yùn)行時(shí)間為任務(wù)信息結(jié)點(diǎn)中的最長(zhǎng)預(yù)期執(zhí)行時(shí)間req.tv_sec = task_node->WCT;req.tv_nsec = 0;// 線程休眠任務(wù)信息結(jié)點(diǎn)中的到達(dá)時(shí)間后再加入管理鏈隊(duì)列,模擬到達(dá)時(shí)間sleep(task_node->arrival_time);// 獲取任務(wù)到達(dá)時(shí)間gettimeofday(&t, 0);start_us = (long)(t.tv_sec * 1000 * 1000) + t.tv_usec;add_task(task_node, sched.schedule_policy);// 獲取任務(wù)開(kāi)始時(shí)間gettimeofday(&t_time, 0);run_us = (long)(t_time.tv_sec * 1000 * 1000) + t_time.tv_usec;// 打印這個(gè)執(zhí)行任務(wù)的線程的開(kāi)始任務(wù)時(shí)間點(diǎn),測(cè)試用printf("Task ptid = %ld starts at Time: %lf sec\n", pthread_self(), (double)(run_us - begin_us) / 1000000.0);// 線程先阻塞,等待調(diào)度器調(diào)度sem_wait(&task_node->wait_sem);// 線程休眠時(shí)間模擬執(zhí)行時(shí)間,如果有信號(hào)中斷,ret返回-1,剩余時(shí)間存儲(chǔ)rem中ret = nanosleep(&req, &rem);// 返回中斷后繼續(xù)休眠剩余時(shí)間模擬完整執(zhí)行時(shí)間while (ret < 0) {req = rem;ret = nanosleep(&req, &rem);}// 獲取結(jié)束時(shí)間gettimeofday(&t, 0);end_us = (long)(t.tv_sec * 1000 * 1000) + t.tv_usec;// 打印任務(wù)結(jié)束時(shí)間gettimeofday(&t_time, 0);run_us = (long)(t_time.tv_sec * 1000 * 1000) + t_time.tv_usec;// 打印這個(gè)執(zhí)行任務(wù)的線程的結(jié)束任務(wù)時(shí)間點(diǎn),測(cè)試用printf("Task ptid = %ld ends at Time: %lf sec\n", pthread_self(), (double)(run_us - begin_us) / 1000000.0);// 等待時(shí)間為實(shí)際運(yùn)行時(shí)間減去預(yù)期執(zhí)行時(shí)間wait_sum_time += end_us - start_us - task_node->WCT * 1000 * 1000;// 執(zhí)行完后從管理鏈隊(duì)列中刪除任務(wù)結(jié)點(diǎn)delete_task();// 調(diào)度器已完成的任務(wù)數(shù)加一sched.finished_task++;pthread_exit(0); }// 發(fā)送信號(hào)阻塞線程,直到接收到一個(gè)新的信號(hào) void thread_wait_sighand(int signo) {// 獲取當(dāng)前時(shí)間gettimeofday(&t_time, 0);run_us = (long)(t_time.tv_sec * 1000 * 1000) + t_time.tv_usec;// 打印這個(gè)執(zhí)行任務(wù)的線程的阻塞時(shí)間點(diǎn),測(cè)試用printf("Task ptid = %ld stops at Time: %lf sec\n", pthread_self(), (double)(run_us - begin_us) / 1000000.0);sigsuspend(&zeromask); }// 發(fā)送信號(hào)使阻塞線程繼續(xù)運(yùn)行 void thread_cont_sighand(int signo) {// 獲取當(dāng)前時(shí)間gettimeofday(&t_time, 0);run_us = (long)(t_time.tv_sec * 1000 * 1000) + t_time.tv_usec;// 打印這個(gè)執(zhí)行任務(wù)的線程的阻塞之后繼續(xù)運(yùn)行時(shí)間點(diǎn),測(cè)試用printf("Task ptid = %ld continues at Time: %lf sec\n", pthread_self(), (double)(run_us - begin_us) / 1000000.0); }// 調(diào)度器線程接收信號(hào)后調(diào)度器選擇一個(gè)任務(wù),即表頭任務(wù)運(yùn)行 void sched_run_sighand(int signo) {// 如果這個(gè)任務(wù)處于阻塞態(tài),那么先轉(zhuǎn)為就緒態(tài),再轉(zhuǎn)為運(yùn)行態(tài),用sem_post()函數(shù)開(kāi)始運(yùn)行任務(wù)if (sched.head->schedule_status == STATUS_WAITING) {sched.head->schedule_status = STATUS_READY;sched.head->schedule_status = STATUS_RUNNING;sem_post(&sched.head->wait_sem);// 獲取任務(wù)執(zhí)行時(shí)間點(diǎn) gettimeofday(&t_time, 0);run_us = (long)(t_time.tv_sec * 1000 * 1000) + t_time.tv_usec;// 打印這個(gè)執(zhí)行任務(wù)的線程的運(yùn)行任務(wù)時(shí)間點(diǎn),測(cè)試用printf("Task ptid = %ld starts to run at Time: %lf sec\n", sched.head->ptid, (double)(run_us - begin_us) / 1000000.0);}// 如果這個(gè)任務(wù)處于就緒態(tài),那么轉(zhuǎn)為運(yùn)行態(tài),發(fā)送信號(hào)使其繼續(xù)運(yùn)行else if (sched.head->schedule_status == STATUS_READY) {sched.head->schedule_status = STATUS_RUNNING;pthread_kill(sched.head->ptid, SIGCONT);} }// 打印任務(wù)信息列表,測(cè)試用 void print_tasklist(int *arrival_time, int *WCT, int *priority, int task_num) {printf("Task list:\n");printf("------------------------------\n");printf("|Id|Arrival time|WCT|Priority|\n");printf("------------------------------\n");for (int i = 0; i < task_num; ++i) {printf("|%2d| %3d |%3d| %2d |\n", i + 1, arrival_time[i], WCT[i], priority[i]);}printf("------------------------------\n");printf("\n"); }// 計(jì)算任務(wù)平均等待時(shí)間 double cal_aver_wait_time(int *arrival_time, int *WCT, int *priority, int task_num, int sched_policy) {int ret;pthread_t ptid[MAX_TASK_NUM];double aver_wait_time;printf("\n----------------------------------------------------------\n");printf("schedule policy: ");// 打印調(diào)度策略switch (sched_policy) {case POLICY_FCFS :printf("FCFS\n\n");break;case POLICY_SJF_PEM:printf("SJF(preemptive)\n\n");break;case POLICY_SJF_NOT_PEM:printf("SJF(not preemptive)\n\n");break;case POLICY_PRIORITY_PEM:printf("Priority(preemptive)\n\n");break;case POLICY_PRIORITY_NOT_PEM:printf("Priority(not preemptive)\n\n");break;}// 打印任務(wù)列表print_tasklist(arrival_time, WCT, priority, task_num);// 設(shè)置調(diào)度策略sched.schedule_policy = sched_policy;wait_sum_time = 0;// 獲取計(jì)時(shí)開(kāi)始時(shí)間gettimeofday(&t_time, 0);begin_us = (long)(t_time.tv_sec * 1000 * 1000) + t_time.tv_usec;// 根據(jù)信息創(chuàng)建任務(wù)信息結(jié)點(diǎn)和相應(yīng)的線程for (int i = 0; i < task_num; i++) {Tasknode *new_node = creat_thread_node(arrival_time[i], WCT[i], priority[i]);ret = pthread_create(&ptid[i], NULL, &task_runner, (void *)new_node);if(ret != 0) {fprintf(stderr, "pthread_create error: %s\n", strerror(ret));exit(1);}printf("Task%d ptid:%ld\n", i + 1, ptid[i]);}printf("\n");// 主線程等待所有子線程運(yùn)行結(jié)束后再繼續(xù)執(zhí)行for (int i = 0; i < task_num; i++) {ret = pthread_join(ptid[i], NULL);if(ret != 0) {fprintf(stderr, "pthread_join error: %s\n", strerror(ret));exit(1);}}// 計(jì)算任務(wù)平均等待時(shí)間printf("\nThe waiting time = %lf sec\n", (double)wait_sum_time / 1000000.0);aver_wait_time = (double)wait_sum_time / 1000000.0 / (double)task_num;printf("The average of waiting time = %lf sec\n", aver_wait_time);printf("----------------------------------------------------------\n");return aver_wait_time; }int main() {int arrival_time[MAX_TASK_NUM];int WCT[MAX_TASK_NUM];int priority[MAX_TASK_NUM];int task_num;printf("Please input the number of tasks: ");scanf("%d", &task_num);// 設(shè)置不同捕捉信號(hào)的信號(hào)處理函數(shù)struct sigaction act1, act2, act3;memset(&act1, 0, sizeof(act1));memset(&act2, 0, sizeof(act2));memset(&act3, 0, sizeof(act3));sigemptyset(&act1.sa_mask);sigemptyset(&act2.sa_mask);sigemptyset(&act3.sa_mask);act1.sa_flags = 0;act2.sa_flags = 0;act3.sa_flags = 0;act1.sa_handler = thread_wait_sighand;act2.sa_handler = thread_cont_sighand;act3.sa_handler = sched_run_sighand;// 設(shè)置捕捉到SIGUSR1后信號(hào)處理函數(shù)為使線程阻塞sigaction(SIGUSR1, &act1, NULL);// 設(shè)置捕捉到SIGCONT后信號(hào)處理函數(shù)為使阻塞的線程繼續(xù)sigaction(SIGCONT, &act2, NULL);// 設(shè)置捕捉到SIGUSR2后信號(hào)處理函數(shù)為使調(diào)度器選擇一個(gè)任務(wù)運(yùn)行sigaction(SIGUSR2, &act3, NULL);// 初始化調(diào)度器init_scheduler(task_num);// 輸入每個(gè)任務(wù)的到達(dá)時(shí)間,最長(zhǎng)預(yù)期運(yùn)行時(shí)間,優(yōu)先級(jí)等for (int i = 0; i < task_num; i++) {printf("Please input task%d's arrival_time, WCT, priority:\n", i + 1);scanf("%d %d %d", &arrival_time[i], &WCT[i], &priority[i]);}double aver_wait_time_fcfs = cal_aver_wait_time(arrival_time, WCT, priority, task_num, POLICY_FCFS);double aver_wait_time_sjf_pem = cal_aver_wait_time(arrival_time, WCT, priority, task_num, POLICY_SJF_PEM);double aver_wait_time_sjf_not_pem = cal_aver_wait_time(arrival_time, WCT, priority, task_num, POLICY_SJF_NOT_PEM);double aver_wait_time_priority_pem = cal_aver_wait_time(arrival_time, WCT, priority, task_num, POLICY_PRIORITY_PEM);double aver_wait_time_priority_not_pem = cal_aver_wait_time(arrival_time, WCT, priority, task_num, POLICY_PRIORITY_NOT_PEM);// 打印不同調(diào)度策略平均等待時(shí)間列表printf("\nAverage waiting time list(sec):\n");printf("-----------------------------------------------\n");printf("| Policy |Average waiting time|\n");printf("-----------------------------------------------\n");printf("| FCFS | %10lf |\n", aver_wait_time_fcfs);printf("| SJF(preemptive) | %10lf |\n", aver_wait_time_sjf_pem);printf("| SJF(not preemptive) | %10lf |\n", aver_wait_time_sjf_not_pem);printf("| Priority(preemptive) | %10lf |\n", aver_wait_time_priority_pem);printf("|Priority(not preemptive)| %10lf |\n", aver_wait_time_priority_not_pem);printf("-----------------------------------------------\n"); }

執(zhí)行命令:

gcc scheduler.c -pthread ./a.out

驗(yàn)證各個(gè)調(diào)度算法的正確性

測(cè)試用例1:

3 0 5 1 2 4 3 4 3 2 TaskArrival TimeWCTPriority
1051
2243
3432

先到先服務(wù)調(diào)度策略:

可以看到,任務(wù)1在0s時(shí)開(kāi)始執(zhí)行;
在2s時(shí)任務(wù)2到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)2后調(diào)度器根據(jù)先到先服務(wù)策略繼續(xù)選擇任務(wù)1執(zhí)行,任務(wù)1在2s時(shí)繼續(xù)執(zhí)行,任務(wù)2阻塞;
在4s時(shí)任務(wù)3到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)3后調(diào)度器根據(jù)先到先服務(wù)策略繼續(xù)選擇任務(wù)1執(zhí)行,任務(wù)1在4s時(shí)繼續(xù)執(zhí)行,任務(wù)3阻塞;
在5s時(shí)任務(wù)1結(jié)束,調(diào)度器根據(jù)先到先服務(wù)策略選擇任務(wù)2執(zhí)行,任務(wù)2在5s繼續(xù)執(zhí)行;
在9s時(shí)任務(wù)2結(jié)束,調(diào)度器根據(jù)先到先服務(wù)策略選擇任務(wù)3執(zhí)行,任務(wù)2在9s繼續(xù)執(zhí)行;
在12s時(shí)任務(wù)3結(jié)束,任務(wù)全部完成。

過(guò)程符合先到先服務(wù)的調(diào)度策略。

甘特圖:

計(jì)算等待時(shí)間為 (0 - 0) + (5 - 2) + (9 - 4) = 8
計(jì)算平均等待時(shí)間為 8 / 3 = 2.67s
計(jì)算也正確。

搶占式最短作業(yè)優(yōu)先調(diào)度策略:

可以看到,任務(wù)1在0s時(shí)開(kāi)始執(zhí)行;
在2s時(shí)任務(wù)2到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)2后,由于任務(wù)2的WCT比任務(wù)1小,所以調(diào)度器根據(jù)搶占式最短作業(yè)優(yōu)先調(diào)度策略,選擇任務(wù)2執(zhí)行,任務(wù)2在2s時(shí)開(kāi)始執(zhí)行,任務(wù)1阻塞;
在4s時(shí)任務(wù)3到達(dá),運(yùn)行著的任務(wù)2先阻塞,加入任務(wù)3后,由于任務(wù)3的WCT比任務(wù)2小,所以調(diào)度器根據(jù)搶占式最短作業(yè)優(yōu)先調(diào)度策略選擇任務(wù)3執(zhí)行,任務(wù)3在4s時(shí)開(kāi)始執(zhí)行,任務(wù)2阻塞;
在7s時(shí)任務(wù)3結(jié)束,調(diào)度器根據(jù)搶占式最短作業(yè)優(yōu)先調(diào)度策略選擇任務(wù)2執(zhí)行,任務(wù)2在7s繼續(xù)執(zhí)行;
在9s時(shí)任務(wù)2結(jié)束,調(diào)度器根據(jù)搶占式最短作業(yè)優(yōu)先調(diào)度策略選擇任務(wù)1執(zhí)行,任務(wù)1在9s繼續(xù)執(zhí)行;
在12s時(shí)任務(wù)3結(jié)束,任務(wù)全部完成。

過(guò)程符合搶占式最短作業(yè)優(yōu)先的調(diào)度策略。

甘特圖:

計(jì)算等待時(shí)間為 (9 - 2) + (7 - 4) + (4 - 4) = 10
計(jì)算平均等待時(shí)間為 10 / 3 = 3.33s
計(jì)算也正確。

非搶占式最短作業(yè)優(yōu)先調(diào)度策略:

可以看到,任務(wù)1在0s時(shí)開(kāi)始執(zhí)行;
在2s時(shí)任務(wù)2到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)2后,雖然任務(wù)2的WCT比任務(wù)1小,但是調(diào)度器根據(jù)非搶占式最短作業(yè)優(yōu)先調(diào)度策略,繼續(xù)選擇任務(wù)1執(zhí)行,任務(wù)1在2s時(shí)繼續(xù)執(zhí)行,任務(wù)2阻塞;
在4s時(shí)任務(wù)3到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)3后,雖然任務(wù)3的WCT比任務(wù)1小,但是調(diào)度器根據(jù)非搶占式最短作業(yè)優(yōu)先調(diào)度策略繼續(xù)選擇任務(wù)1執(zhí)行,任務(wù)1在4s時(shí)繼續(xù)執(zhí)行,任務(wù)3阻塞;
在5s時(shí)任務(wù)1結(jié)束,調(diào)度器根據(jù)非搶占式最短作業(yè)優(yōu)先調(diào)度策略選擇WCT更小的任務(wù)3執(zhí)行,任務(wù)3在5s繼續(xù)執(zhí)行;
在8s時(shí)任務(wù)3結(jié)束,調(diào)度器根據(jù)非搶占式最短作業(yè)優(yōu)先調(diào)度策略選擇任務(wù)2執(zhí)行,任務(wù)2在8s繼續(xù)執(zhí)行;
在12s時(shí)任務(wù)2結(jié)束,任務(wù)全部完成。

過(guò)程符合非搶占式最短作業(yè)優(yōu)先的調(diào)度策略。

甘特圖:

計(jì)算等待時(shí)間為 (0 - 0) + (8 - 2) + (5 - 4) = 7
計(jì)算平均等待時(shí)間為 7 / 3 = 2.33s
計(jì)算也正確。

搶占式優(yōu)先級(jí)調(diào)度策略:

可以看到,任務(wù)1在0s時(shí)開(kāi)始執(zhí)行;
在2s時(shí)任務(wù)2到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)2后,由于任務(wù)2的優(yōu)先級(jí)比任務(wù)1大,所以調(diào)度器根據(jù)搶占式優(yōu)先級(jí)調(diào)度策略,選擇任務(wù)2執(zhí)行,任務(wù)2在2s時(shí)開(kāi)始執(zhí)行,任務(wù)1阻塞;
在4s時(shí)任務(wù)3到達(dá),運(yùn)行著的任務(wù)2先阻塞,加入任務(wù)3后,由于任務(wù)3的優(yōu)先級(jí)比任務(wù)2小,所以調(diào)度器根據(jù)搶占式優(yōu)先級(jí)調(diào)度策略繼續(xù)選擇任務(wù)2執(zhí)行,任務(wù)2在4s時(shí)繼續(xù)執(zhí)行,任務(wù)3阻塞;
在6s時(shí)任務(wù)2結(jié)束,調(diào)度器根據(jù)搶占式優(yōu)先級(jí)調(diào)度策略選擇優(yōu)先級(jí)更大的任務(wù)3執(zhí)行,任務(wù)3在6s繼續(xù)執(zhí)行;
在9s時(shí)任務(wù)3結(jié)束,調(diào)度器根據(jù)搶占式優(yōu)先級(jí)調(diào)度策略選擇任務(wù)1執(zhí)行,任務(wù)1在9s繼續(xù)執(zhí)行;
在12s時(shí)任務(wù)1結(jié)束,任務(wù)全部完成。

過(guò)程符合搶占式優(yōu)先級(jí)的調(diào)度策略。

甘特圖:

計(jì)算等待時(shí)間為 (9 - 2) + (2 - 2) + (6 - 4) = 9
計(jì)算平均等待時(shí)間為 9 / 3 = 3s
計(jì)算也正確。

非搶占式優(yōu)先級(jí)調(diào)度策略:

可以看到,任務(wù)1在0s時(shí)開(kāi)始執(zhí)行;
在2s時(shí)任務(wù)2到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)2后,雖然任務(wù)2的優(yōu)先級(jí)比任務(wù)1大,但是調(diào)度器根據(jù)非搶占式優(yōu)先級(jí)調(diào)度策略,繼續(xù)選擇任務(wù)1執(zhí)行,任務(wù)1在2s時(shí)繼續(xù)執(zhí)行,任務(wù)2阻塞;
在4s時(shí)任務(wù)3到達(dá),運(yùn)行著的任務(wù)1先阻塞,加入任務(wù)3后,雖然任務(wù)3的優(yōu)先級(jí)比任務(wù)1大,但是調(diào)度器根據(jù)非搶占式優(yōu)先級(jí)調(diào)度策略繼續(xù)選擇任務(wù)1執(zhí)行,任務(wù)1在4s時(shí)繼續(xù)執(zhí)行,任務(wù)3阻塞;
在5s時(shí)任務(wù)1結(jié)束,調(diào)度器根據(jù)非搶占式優(yōu)先級(jí)調(diào)度策略選擇優(yōu)先級(jí)更大的任務(wù)2執(zhí)行,任務(wù)2在5s繼續(xù)執(zhí)行;
在9s時(shí)任務(wù)2結(jié)束,調(diào)度器根據(jù)非搶占式優(yōu)先級(jí)調(diào)度策略選擇任務(wù)3執(zhí)行,任務(wù)3在9s繼續(xù)執(zhí)行;
在12s時(shí)任務(wù)3結(jié)束,任務(wù)全部完成。

過(guò)程符合非搶占式優(yōu)先級(jí)的調(diào)度策略。

甘特圖:

計(jì)算等待時(shí)間為 (0 - 0) + (5 - 2) + (9 - 4) = 8
計(jì)算平均等待時(shí)間為 8 / 3 = 2.67s
計(jì)算也正確。

可以看出,各個(gè)調(diào)度算法基本正確。

測(cè)試用例2:

5 0 3 1 2 6 3 4 4 4 6 5 2 8 2 5 TaskArrival TimeWCTPriority
1031
2263
3444
4652
5825

執(zhí)行截圖:

甘特圖:

[(0 - 0) + (3 - 2) + (9 - 4) + (13 - 6) + (18 - 8)] / 5 = 23 / 5 = 4.6

[(0 - 0) + (3 - 2 + 15 - 2) + (4 - 4) + (10 - 6) + (8 - 8)] / 5 = 18 / 5 = 3.6

[(0 - 0) + (3 - 2) + (11 - 4) + (15 - 6) + (9 - 8)] / 5 = 18 / 5 = 3.6

[(19 - 0) + (10 - 2) + (4 - 4) + (14 - 6) + (8 - 8)] / 5 = 33 / 5 = 6.6

[(0 - 0) + (3 - 2) + (11 - 4) + (15 - 6) + (9 - 8)] / 5 = 18 / 5 = 3.6

經(jīng)過(guò)計(jì)算,結(jié)果基本正確。

測(cè)試用例3:

4 0 7 1 2 4 3 4 1 4 5 4 2 TaskArrival TimeWCTPriority
1071
2243
3414
4542

執(zhí)行截圖:

經(jīng)過(guò)計(jì)算,結(jié)果基本正確。

測(cè)試用例4:

4 0 8 1 1 4 3 2 9 4 3 5 2 TaskArrival TimeWCTPriority
1081
2143
3294
4352

執(zhí)行截圖:

經(jīng)過(guò)計(jì)算,結(jié)果基本正確。

總結(jié)

以上是生活随笔為你收集整理的操作系统实验报告16:CPU 调度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。