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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

操作系统课程设计--模拟时间片轮转法

發布時間:2023/12/15 windows 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 操作系统课程设计--模拟时间片轮转法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

課程設計題目

設計一個按照時間片輪轉法實現處理機調度的程序。

實驗內容

(1) 假設系統有n個進程,每個進程用一個進程控制塊(PCB)來代表。進程控制塊的格式如下表所示,且參數意義也相同。

進程名
鏈接指針
到達時間
估計運行時間
進程狀態

(2) 按照進程到達的先后順序排成一個循環隊列,設一個隊首指針指向第一個到達進程的首址。另外再設一個當前運行進程指針,指向當前正運行的進程。

(3) 執行處理機調度時,首先選擇隊首的第一個進程運行。

(4) 由于本題目是模擬實驗,所以對被選中的進程并不實際啟動運行,而只是執行如下操作:

1)估計運行時間減1;

2)輸出當前運行進程的名字。

用這兩個操作來模擬進程的一次運行。

(5) 進程運行一次后,以后的調度則將當前指針依次下移一個位置,指向下一個進程,即調整當前運行指針指向該進程的鏈接指針所指進程,以指示應運行進程,同時還應判斷該進程的剩余運行時間是否為0,若不為0,則等待下一輪的運行,若該進程的剩余運行時間為0,則將該進程的狀態置為完成狀態“C”,并退出循環隊列。

(6) 若就緒隊列不為空,則重復上述的步驟(4)和(5)直到所有進程都運行完為止。

(7) 在所設計的調度程序中,應包含顯示或打印語句,以便顯示或打印每次選中進程的名稱及運行一次后隊列的變化情況。

算法流程圖

使用的數據結構及主要符號說明

本實驗使用了一個結構表示進程控制塊(PCB),其所有的屬性以及含義如下:

typedef struct PCB //PCB結構 {int name; //進程名字int arrivalTime; //進程到達時間int needTime; //進程需要運行的時間int serverTime; //進程已經運行的時間int leftSysTime; //進程結束時系統時間int flag; //進程狀態,(1-已完成,0-未完成)struct PCB* next; //鏈接指針 }PCB;

為了方便整個流程的操作,本實驗使用了鏈式隊列對進程的操作。下面的initQueue隊列是保存初始化得到的進程,每個進程按照“進程到達時間”升序排列initQueue隊列中。而readyQueue隊列是進程的就緒隊列,系統在readyQueue隊列的隊頭取一個進程運行,根據系統時間從initQueue隊列中取出到達時間合適的進程插到readyQueue隊列的隊尾,然后再將剛剛運行完的進程插入到隊尾。endQueue隊列是用來存放已經運行結束的進程,此隊列用于計算平均周轉時間和平均帶權周轉時間。

typedef struct PCBQueue //隊列 {struct PCB* front; //指向隊頭struct PCB* rear; //指向隊尾 }PCBQueue;PCBQueue* initQueue = (PCBQueue*)malloc(sizeof(PCBQueue)); //初始化隊列 PCBQueue* readyQueue = (PCBQueue*)malloc(sizeof(PCBQueue)); //就緒隊列 PCBQueue* endQueue = (PCBQueue*)malloc(sizeof(PCBQueue)); //已經結束的進程隊列

源代碼

//RoudRobin.c #include<stdio.h> #include<stdlib.h> #include<time.h>typedef struct PCB //PCB結構 {int name; //進程名字int arrivalTime; //進程到達時間int needTime; //進程需要運行的時間int serverTime; //進程已經運行的時間int leftSysTime; //進程結束時系統時間int flag; //進程狀態,(1-已完成,0-未完成)struct PCB* next; //鏈接指針 }PCB;typedef struct PCBQueue //隊列 {struct PCB* front; //指向隊頭struct PCB* rear; //指向隊尾 }PCBQueue;int systime; //系統運行時間 int processes; //進程個數//初始化數據 PCBQueue* Init() {srand(time(NULL));processes = rand() % 15 + 5; //隨機初始化processes個進程個數systime = 0;PCBQueue* initQueue = (PCBQueue*)malloc(sizeof(PCBQueue)); //初始化隊列if (!initQueue)exit(-1);initQueue->front = initQueue->rear = NULL;PCB* p = (PCB*)malloc(sizeof(PCB)); //初始化隊列添加一個頭節點if (!p)exit(-1);p->arrivalTime = -1;p->next = NULL;initQueue->front = initQueue->rear = p;for (int i = 1; i <= processes; i++){p = (PCB*)malloc(sizeof(PCB)); //初始化隊列添加進程p->name = i; //進程的名字if (i <= 2) //進程到達的時間p->arrivalTime = rand() % i;elsep->arrivalTime = rand() % (i + 7);p->needTime = rand() % 5 + 2; //進程需要運行的時間p->flag = 0;p->serverTime = 0;PCB* temp = initQueue->front;while (temp) //根據新生成的PCB在初始化隊列initQueue中找到合適的位置{if (p->arrivalTime >= temp->arrivalTime){initQueue->rear = temp;temp = temp->next;}elsebreak;}//將新生成的PCB插入到初始化隊列initQueue中合適的位置p->next = temp;initQueue->rear->next = p;initQueue->rear = initQueue->front;}//打印printf("申請CPU的進程名、到達時間、運行時間如下:\n");printf("進程 到達時間 運行時間\n");for (int i = 0; i < processes; i++){initQueue->rear = initQueue->rear->next;if (initQueue->rear)printf("p%-3d %6d %10d\n", initQueue->rear->name, initQueue->rear->arrivalTime, initQueue->rear->needTime);}printf("\n");//刪除多余的頭節點p = initQueue->front;initQueue->rear = initQueue->front = initQueue->front->next;free(p);return initQueue; }//在初始化隊列中找出某個系統時間剛好到達的進程放到就緒隊列中 void Fine(PCBQueue* initQueue, PCBQueue* readyQueue) {while (initQueue->front != NULL) //遍歷就緒隊列{if (initQueue->front->arrivalTime == systime) //將就緒隊列中‘當前系統時間’的進程添加到就緒隊列{if (readyQueue->front == NULL){readyQueue->front = readyQueue->rear = initQueue->front;initQueue->front = initQueue->front->next;readyQueue->rear->next = NULL;}else{readyQueue->rear->next = initQueue->front;readyQueue->rear = initQueue->front;initQueue->front = initQueue->front->next;readyQueue->rear->next = NULL;}}elsebreak;} }void CalTime(PCBQueue* e) {PCB* p;int turnoverTime = 0, temp1; //平均周轉時間float turnoverTimeAvg = 0, temp2; //平均帶權周轉時間printf("所有進程運行結束!\n\n");printf("------------------時間片輪轉法性能指標------------------\n");printf("進程名 到達時間 運行時間 結束時間 周轉時間 帶權周轉時間\n");while (e->front){temp1 = e->front->leftSysTime - e->front->arrivalTime;temp2 = (float)temp1 / e->front->needTime;turnoverTime += temp1; //平均周轉時間turnoverTimeAvg += temp2; //平均帶權周轉時間printf(" p%-3d %5d %7d %9d %9d %15f\n", e->front->name, e->front->arrivalTime, e->front->needTime, e->front->leftSysTime, temp1, temp2);p = e->front;e->front = e->front->next;free(p);}printf("平均周轉時間:%f,平均帶權周轉時間:%f\n", (float)turnoverTime / processes, turnoverTimeAvg / processes); }//模擬執行 void SimRun(PCBQueue* initQueue) {PCBQueue* endQueue = (PCBQueue*)malloc(sizeof(PCBQueue)); //已經結束的進程隊列if (!endQueue)exit(-1);endQueue->rear = endQueue->front = NULL;PCBQueue* readyQueue = (PCBQueue*)malloc(sizeof(PCBQueue)); //就緒隊列if (!readyQueue)exit(-1);readyQueue->rear = readyQueue->front = NULL;Fine(initQueue, readyQueue); //從初始化隊列找出現在系統時間到達的進程放到就緒隊列printf("以上所有進程運行過程和每時刻進程就緒隊列情況如下:\n");while (initQueue->front || readyQueue->front){if (readyQueue->front) //就緒隊列不為空{PCB* p = readyQueue->front;printf("系統時間:%d\t正在運行的進程:p%-3d 就緒隊列:", systime, p->name); //打印正在執行的進程、就緒隊列p = readyQueue->front->next;while (p){printf("p%-2d ", p->name);p = p->next;}printf("\n");p = readyQueue->front;p->serverTime += 1;systime += 1;Fine(initQueue, readyQueue); //進程運行完后理論上要進行“保護現場”,所以應該先讓這個時刻到達的進程插入就緒隊列最后if (p->needTime == p->serverTime) //該進程已經運行完了{p->leftSysTime = systime;p->flag = 1; //進程狀態改變readyQueue->front = readyQueue->front->next;p->next = NULL;if (endQueue->front == NULL){endQueue->front = endQueue->rear = p;}else{endQueue->rear->next = p;endQueue->rear = p;}}else //進程還沒執行完,插入到就緒隊列最后{if (readyQueue->front != readyQueue->rear){readyQueue->front = readyQueue->front->next;readyQueue->rear->next = p;readyQueue->rear = p;readyQueue->rear->next = NULL;}elsereadyQueue->front = readyQueue->rear;}}else if (initQueue->front) //就緒隊列為空,初始化隊列不為空{printf("系統時間:%d\t正在運行的進程:無 等待隊列:無\n", systime);systime += 1;Fine(initQueue, readyQueue);}else //就緒隊列、初始化隊列均為空break;}CalTime(endQueue); //計算周轉時間free(readyQueue); //釋放內存free(initQueue);free(endQueue); }void main() {PCBQueue* initQueue = NULL;int number = 1;while (number != 3){printf("----------時間片輪轉法----------\n");printf("1.運行時間片輪轉法算法\n");printf("2.清空屏幕\n");printf("3.退出程序\n");scanf_s("%d", &number);switch (number){case 1:initQueue = Init(); //返回按照進程到達的先后順序排成一個隊列SimRun(initQueue); //模擬運行printf("\n");break;case 2:system("clear");break;case 3:break;default:printf("輸入錯誤\n");}} }

實驗結果截圖





實驗分析

輸出結果說明:系統時間:是用來記錄模擬記錄進程到達時間和進程運行時間,時間片輪轉開始的時候設時間為0,每個進程運行一個時間片時系統時間加1;正在運行的進程:是指從就緒隊列中取出合適的進程運行;就緒隊列:是指這個時間(系統時間)去掉剛取出的運行的進程,剩余在等待運行的進程的隊列。

根據最后一個實驗結果,進程P1、是在系統時間為0時刻就到達了,這個時候先將進程P1從初始化隊列initQueue取出并且插到就緒隊列readyQueue中,接著從就緒隊列readyQueue隊頭取出進程P1,P1運行一個時間片,系統時間+1,P1結束后查看P1的運行時間是否已經滿足,如果滿足則改變進程狀態并且移出就緒隊列;否則查看初始化隊列有沒有進程到達時間與系統時間相等,有則取出插入到就緒隊列后面,沒有就直接將剛剛運行的還沒結束的進程插入到就緒隊列后面。如此重復。例如最后一個實驗結果中系統時間為第1秒時,進程P1運行結束了,這個時候進程P2到達了,而P2應該先插入到就緒隊列后面,然后如果P1還沒滿足運行時間就插在就緒隊列最后面,即P2后面。

本實驗通過初始化得到一個進程等待隊列,模擬進程在不同時間申請CPU資源,通過一個就緒隊列模擬進程的調度、執行過程。通過大量的實驗結果驗證得到該程序正確地實現了時間片輪轉算法模擬。

實驗收獲和體會

通過這次課程設計,我對時間片輪轉調度算法進行了大量的資料查詢,從而對時間片輪轉調度算法思想有了更深的理解,對該算法的操作也有了熟練的操作;另外通過大量的鏈表操作,我對鏈表的知識有了更深的理解,而且鍛煉了我的思維能力,我能更全面地思考問題。

時間片輪轉算法是系統將所有的就緒進程按先來先服務算法的原則,排成一個隊列,每次調度時,系統把處理機分配給隊列首進程,并讓其執行一個時間片。當執行的時間片用完時,由一個計時器發出時鐘中斷請求,調度程序根據這個請求停止該進程的運行,將它送到就緒隊列的末尾,再把處理機分給就緒隊列中新的隊列首進程,同時讓它也執行一個時間片。

實驗的改進意見和建議。

該實驗的提示中做給的進程控制塊(PCB)的格式中“進程狀態”這一屬性其實在本次模擬實驗中用處不大,因為如果一個進程運行完后,可以直接從就緒隊列中刪除掉,而不需要更改這個“進程狀態”,更改后又不起作用;而且刪除后就緒隊列就會減短,遍歷的時候可以省略掉對每個進程是否已經結束的判斷,從而減少運行時間。

總結

以上是生活随笔為你收集整理的操作系统课程设计--模拟时间片轮转法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。