2020-04-06

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#define TRUE 1

#define FALSE 0

//作業(yè)數(shù)組大小

#define LEN 5

/*

**

** 各種調(diào)度算法模擬仿真(鏈?zhǔn)酱鎯Φ年犃袑崿F(xiàn)版):

** 短作業(yè)優(yōu)先調(diào)度算法 (SJF)、先來先服務(wù)調(diào)度算法 (FCFS)

** 時間片輪轉(zhuǎn)調(diào)度算法 (RR) 、最高響應(yīng)比調(diào)度算法(HRRN)?

** Author:賈志洋

** version:1.0

** Create Time: 2020/4/05 22:09

** Modified Time:

*/

/*進程PCB結(jié)點結(jié)構(gòu)體*/

typedef struct job

{

int PID; //進程的PID

int arrival_time; //進程到達系統(tǒng)時間

int require_time_slice; //要求服務(wù)時間

int used_time_slice; //已經(jīng)使用的時間片(短作業(yè)優(yōu)先用不到該值)

int ended_time; //進程完成時間 ,初始值為-1,表示進程未完成,如果該進程已經(jīng)完成則>=0

int waited_time; //等待時間,等待時間=周轉(zhuǎn)時間-要求服務(wù)時間

int cycle_time; //周轉(zhuǎn)時間,周轉(zhuǎn)時間=結(jié)束時間-到達時間

float weight_cycle_time; //帶權(quán)周轉(zhuǎn)時間,帶權(quán)周轉(zhuǎn)時間=周轉(zhuǎn)時間/要求服務(wù)時間

struct job * next; //所在隊列的下一個作業(yè)

}job;

/*作業(yè)隊列的結(jié)構(gòu)體*/

typedef struct linked_queue

{

job * front; //隊頭指向結(jié)點的指針

job * rear; //隊尾指向結(jié)點的指針

int count; //隊列當(dāng)前長度

}linked_queue;

//作業(yè)數(shù)組全局變量

struct job job_array[LEN];

//后備隊列

linked_queue * created_queue;

//就緒隊列

linked_queue * ready_queue;

//完成隊列

linked_queue * ended_queue;

//初始化作業(yè)數(shù)組的每個作業(yè)信息

void init_jobs();

//初始化各個隊列

void init_queues();

//打印菜單

void print_menu();

//短作業(yè)優(yōu)先調(diào)度算法 (SJF)

void sjf_jobs();

//先來先服務(wù)調(diào)度算法 (FCFS)

void fcfs_jobs();

//時間片輪轉(zhuǎn)調(diào)度算法 (RR)

void rr_jobs(int q);

//最高響應(yīng)比調(diào)度算法(HRRN)

void hrrn_jobs();

//打印輸出所有作業(yè)的各種時間平均值

void print_average_value();

//作業(yè)出隊列函數(shù)

job * de_queue(linked_queue * queue);

//返回隊頭作業(yè)(不出隊)

job * peek_queue(linked_queue * queue);

//計算該作業(yè)的各種時間

void record_job_time(job * record_job);

//作業(yè)結(jié)點入隊

void en_queue_node(linked_queue * queue,job * en_queue_pcb_node);

/*程序入口*/

int main()

{

//記錄用戶鍵盤輸入的選擇鍵

char user_opt;

while(1)

{

//初始化作業(yè)數(shù)組中每個作業(yè)

init_jobs();

//初始化各個隊列

init_queues();

//打印菜單

print_menu();

scanf("%c", &user_opt);

getchar();

switch(user_opt)

{

case '1' :

sjf_jobs();

break;

case '2':

fcfs_jobs();

break;

case '3':

rr_jobs(1);

break;

case '4':

rr_jobs(4);

break;

case '5':

hrrn_jobs();

break;

case 'q':

exit(0);

break;

}

}

return 0;

}

void print_menu()

{

printf("\n======================\n");

printf("按1鍵SJF \n");

printf("按2鍵FCFS\n");

printf("按3鍵RR時間片輪轉(zhuǎn)(q=1)\n");

printf("按3鍵RR時間片輪轉(zhuǎn)(q=4)\n");

printf("按3鍵HRRN\n");

printf("按q鍵退出 \n");

printf("您的選擇: \n");

printf("\n======================\n");

}

void init_jobs()

{

//根據(jù)題目要求的表格初始化每個進程的信息(也可以通過控制臺輸入)

job_array[0].PID = 0; job_array[0].require_time_slice = 3; job_array[0].arrival_time = 0; job_array[0].ended_time =-1; job_array[0].used_time_slice = 0;

job_array[1].PID = 1; job_array[1].require_time_slice = 6; job_array[1].arrival_time = 2; job_array[1].ended_time =-1; job_array[1].used_time_slice = 0;

job_array[2].PID = 2; job_array[2].require_time_slice = 4; job_array[2].arrival_time = 4; job_array[2].ended_time =-1; job_array[2].used_time_slice = 0;

job_array[3].PID = 3; job_array[3].require_time_slice = 5; job_array[3].arrival_time = 6; job_array[3].ended_time =-1; job_array[3].used_time_slice = 0;

job_array[4].PID = 4; job_array[4].require_time_slice = 2; job_array[4].arrival_time = 8; job_array[4].ended_time =-1; job_array[4].used_time_slice = 0;

}

void init_queues()

{

//釋放原來的

free(created_queue);

free(ready_queue);

free(ended_queue);

//后備隊列

created_queue = (linked_queue*)malloc(sizeof(linked_queue));

//初始化隊列

created_queue->front = created_queue->rear = NULL;

//就緒隊列

ready_queue = (linked_queue*)malloc(sizeof(linked_queue));

//初始化隊列

ready_queue->front = ready_queue->rear = NULL;

//完成隊列

ended_queue = (linked_queue*)malloc(sizeof(linked_queue));

//初始化隊列

ended_queue->front = ended_queue->rear = NULL;

//將作業(yè)數(shù)組中所有作業(yè)放入后備隊列

int i;

for(i=0;i<LEN;i++)

en_queue_node(created_queue,&job_array[i]);

}

void record_job_time(job * record_job)

{

//計算該作業(yè)的各種時間

record_job->cycle_time = record_job->ended_time - record_job->arrival_time;

record_job->waited_time = record_job->cycle_time - record_job->require_time_slice;

record_job->weight_cycle_time = (float)record_job->cycle_time / (float)record_job->require_time_slice;

}

void print_average_value()

{

//平均周轉(zhuǎn)時間

float avg_cycle_time = 0;

//平均等待時間

float avg_waited_time = 0;

//平均帶權(quán)周轉(zhuǎn)時間

float avg_weight_cycle_time = 0;

//遍歷作業(yè)數(shù)組,求和值

int i;

for(i=0;i<LEN;i++)

{

avg_cycle_time += (float) job_array[i].cycle_time;

avg_waited_time += (float) job_array[i].waited_time;

avg_weight_cycle_time += job_array[i].weight_cycle_time;

}

//計算均值

avg_cycle_time = avg_cycle_time / (float) LEN;

avg_waited_time = avg_waited_time / (float) LEN;

avg_weight_cycle_time = avg_weight_cycle_time / (float) LEN;

printf("平均周轉(zhuǎn)時間:%05.2f平均等待時間:%05.2f平均帶權(quán)周轉(zhuǎn)時間:%05.2f\n",avg_cycle_time,avg_waited_time,avg_weight_cycle_time);

}

void fcfs_jobs()

{

//先來先服務(wù)調(diào)度算法

int current_time = 0;

//當(dāng)前運行的作業(yè)

job * running_job = NULL;

//后備隊列不為空 或 就緒隊列不為空 或 正在有作業(yè)運行? 則進行調(diào)度

while (!is_queue_empty(created_queue)||!is_queue_empty(ready_queue)||running_job!=NULL)

{

//把后備隊列中,到達時間為當(dāng)前系統(tǒng)時間的作業(yè)掛入就緒隊列

while (!is_queue_empty(created_queue))

{

job * front_job = peek_queue(created_queue);

if (front_job->arrival_time==current_time)

{

//后備隊列出隊一個作業(yè)并掛入就緒隊列

en_queue_node(ready_queue,de_queue(created_queue) );

}

else

{

//一定要有else,表示后備隊列中的當(dāng)前隊頭作業(yè)的到達系統(tǒng)時間大于系統(tǒng)當(dāng)前時間,需要退出while循環(huán)

break;

}

}

//判斷當(dāng)前是否有進程使用CPU

if (running_job == NULL)

{

//無作業(yè)使用CPU,將就緒隊列隊頭出隊,去使用CPU

if (!is_queue_empty(ready_queue))

running_job = de_queue(ready_queue);

else

{

//為了增加程序的健壯性,可以用某些其它數(shù)據(jù)測試(本題目要求沒有出現(xiàn)這種情況)

//需要考慮,當(dāng)前就緒隊列為空,但后備隊列仍舊有未到達系統(tǒng)的作業(yè),系統(tǒng)時間空轉(zhuǎn)1個時間片

printf("系統(tǒng)%d時刻就緒隊列空\n", current_time);

current_time++;

continue;

}

//printf("調(diào)度新的作業(yè)使用CPU:%d\n",running_job->PID);

}

else

{

//如果有作業(yè)正在使用CPU,判斷其使用CPU時間是否已經(jīng)滿足其要求服務(wù)時間

if (running_job->used_time_slice==running_job->require_time_slice)

{

//該作業(yè)要求服務(wù)時間已滿足

//記錄作業(yè)完成時間

running_job->ended_time = current_time;

//將該作業(yè)掛入完成隊列

en_queue_node(ended_queue,running_job);

//計算并存儲各種時間

record_job_time(running_job);

printf("調(diào)作業(yè)%d已完成,完成時間:%d\n",running_job->PID,running_job->ended_time);

//從就緒隊列調(diào)度新的作業(yè)使用CPU

if (!is_queue_empty(ready_queue))

running_job = de_queue(ready_queue);

else

running_job = NULL;

}

else

{

//空實現(xiàn)

}

}

//系統(tǒng)時間步進

current_time++;

//當(dāng)前正在運行的作業(yè)的使用的時間片++

if (running_job!=NULL)

running_job->used_time_slice++;

}

printf("SJF的調(diào)度信息:\n");

//打印該調(diào)度算法的各種時間的平均值

print_average_value();

}

void sjf_jobs()

{

//請實現(xiàn),SJF算法

}

void rr_jobs(int q)

{

//請實現(xiàn),時間片輪轉(zhuǎn)RR算法,傳入?yún)?shù)為時間片q的大小

}

void hrrn_jobs()

{

//請實現(xiàn) ,最高響應(yīng)比優(yōu)先算法HRRN(非搶占),

}

//作業(yè)結(jié)點入隊

void en_queue_node(linked_queue * queue,job * en_queue_pcb_node)

{

//將傳入的Job作業(yè)結(jié)點入隊

if (is_queue_empty(queue)){

queue->front = en_queue_pcb_node;

queue->rear = en_queue_pcb_node;

}else{

//隊列非空,

queue->rear->next = en_queue_pcb_node;

queue->rear =? en_queue_pcb_node;

}

}

//判斷隊列是否為空

int is_queue_empty(linked_queue * queue)

{

if ((queue->front==NULL)&&(queue->rear==NULL))

return TRUE;

else

return FALSE;

}

/*遍歷隊列,按順序?qū)㈥犃兄忻總€元素的值打印輸出*/

void show_queue_all_job(linked_queue * queue){

if (is_queue_empty(queue)){

printf("隊列為空,遍歷結(jié)束\n");

return;

}

//游標(biāo)指針

job * cursor_pcb_pointer;

cursor_pcb_pointer = queue->front;

printf("---------------\n");

printf("隊列為:\n");

/*順序遍歷隊列每個結(jié)點*/

while (cursor_pcb_pointer!=NULL){

//打印當(dāng)前結(jié)點信息,

printf("結(jié)點PID:%d,時間片需求為:%d\n",cursor_pcb_pointer->PID,cursor_pcb_pointer->require_time_slice);

//后移游標(biāo)指針

cursor_pcb_pointer=cursor_pcb_pointer->next;

}

printf("---------------\n");

}

job * de_queue(linked_queue * queue)

{

job * return_job;

if (is_queue_empty(queue)){

printf("隊列為空,無法出隊\n");

return NULL;

}

return_job = queue->front;

if (queue->front==queue->rear){

//只有一個結(jié)點時候

queue->front=queue->rear=NULL;

}else{

//多于一個結(jié)點時

queue->front = queue->front->next;

}

return_job->next = NULL;

return return_job;

}

//返回隊頭作業(yè),但不出隊

job * peek_queue(linked_queue * queue)

{

return queue->front;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,958評論 2 373