2020-04-01

include <stdio.h>

include <stdlib.h>

include <malloc.h>

define TRUE 1

define FALSE 0

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

define LEN 5

/*
**
** 各種調(diào)度算法模擬仿真(鏈?zhǔn)酱鎯Φ年?duì)列實(shí)現(xiàn)版):
** 短作業(yè)優(yōu)先調(diào)度算法 (SJF)厅贪、先來先服務(wù)調(diào)度算法 (FCFS)
** 時(shí)間片輪轉(zhuǎn)調(diào)度算法 (RR) 、最高響應(yīng)比調(diào)度算法(HRRN)
** Author:賈志洋
** version:1.0
** Create Time: 2020/4/05 22:09
** Modified Time:
*/

/進(jìn)程PCB結(jié)點(diǎn)結(jié)構(gòu)體/
typedef struct job
{
int PID; //進(jìn)程的PID
int arrival_time; //進(jìn)程到達(dá)系統(tǒng)時(shí)間
int require_time_slice; //要求服務(wù)時(shí)間
int used_time_slice; //已經(jīng)使用的時(shí)間片(短作業(yè)優(yōu)先用不到該值)
int ended_time; //進(jìn)程完成時(shí)間 产园,初始值為-1落君,表示進(jìn)程未完成抢呆,如果該進(jìn)程已經(jīng)完成則>=0
int waited_time; //等待時(shí)間,等待時(shí)間=周轉(zhuǎn)時(shí)間-要求服務(wù)時(shí)間
int cycle_time; //周轉(zhuǎn)時(shí)間,周轉(zhuǎn)時(shí)間=結(jié)束時(shí)間-到達(dá)時(shí)間
float weight_cycle_time; //帶權(quán)周轉(zhuǎn)時(shí)間宇攻,帶權(quán)周轉(zhuǎn)時(shí)間=周轉(zhuǎn)時(shí)間/要求服務(wù)時(shí)間
struct job * next; //所在隊(duì)列的下一個作業(yè)
}job;

/作業(yè)隊(duì)列的結(jié)構(gòu)體/
typedef struct linked_queue
{
job * front; //隊(duì)頭指向結(jié)點(diǎn)的指針
job * rear; //隊(duì)尾指向結(jié)點(diǎn)的指針
int count; //隊(duì)列當(dāng)前長度
}linked_queue;

//作業(yè)數(shù)組全局變量
struct job job_array[LEN];

//后備隊(duì)列
linked_queue * created_queue;
//就緒隊(duì)列
linked_queue * ready_queue;
//完成隊(duì)列
linked_queue * ended_queue;

//初始化作業(yè)數(shù)組的每個作業(yè)信息
void init_jobs();
//初始化各個隊(duì)列
void init_queues();
//打印菜單
void print_menu();
//短作業(yè)優(yōu)先調(diào)度算法 (SJF)
void sjf_jobs();
//先來先服務(wù)調(diào)度算法 (FCFS)
void fcfs_jobs();
//時(shí)間片輪轉(zhuǎn)調(diào)度算法 (RR)
void rr_jobs(int q);
//最高響應(yīng)比調(diào)度算法(HRRN)
void hrrn_jobs();

//打印輸出所有作業(yè)的各種時(shí)間平均值
void print_average_value();
//作業(yè)出隊(duì)列函數(shù)
job * de_queue(linked_queue * queue);
//返回隊(duì)頭作業(yè)(不出隊(duì))
job * peek_queue(linked_queue * queue);
//計(jì)算該作業(yè)的各種時(shí)間
void record_job_time(job * record_job);
//作業(yè)結(jié)點(diǎn)入隊(duì)
void en_queue_node(linked_queue * queue,job * en_queue_pcb_node);

/程序入口/
int main()
{
//記錄用戶鍵盤輸入的選擇鍵
char user_opt;
while(1)
{
//初始化作業(yè)數(shù)組中每個作業(yè)
init_jobs();
//初始化各個隊(duì)列
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時(shí)間片輪轉(zhuǎn)(q=1)\n");
printf("按3鍵RR時(shí)間片輪轉(zhuǎn)(q=4)\n");
printf("按3鍵HRRN\n");
printf("按q鍵退出 \n");
printf("您的選擇: \n");
printf("\n======================\n");
}

void init_jobs()
{
//根據(jù)題目要求的表格初始化每個進(jìn)程的信息(也可以通過控制臺輸入)
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);
//后備隊(duì)列
created_queue = (linked_queue)malloc(sizeof(linked_queue));
//初始化隊(duì)列
created_queue->front = created_queue->rear = NULL;
//就緒隊(duì)列
ready_queue = (linked_queue
)malloc(sizeof(linked_queue));
//初始化隊(duì)列
ready_queue->front = ready_queue->rear = NULL;
//完成隊(duì)列
ended_queue = (linked_queue*)malloc(sizeof(linked_queue));
//初始化隊(duì)列
ended_queue->front = ended_queue->rear = NULL;

//將作業(yè)數(shù)組中所有作業(yè)放入后備隊(duì)列
int i;
for(i=0;i<LEN;i++)
    en_queue_node(created_queue,&job_array[i]);

}

void record_job_time(job * record_job)
{
//計(jì)算該作業(yè)的各種時(shí)間
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)時(shí)間
float avg_cycle_time = 0;
//平均等待時(shí)間
float avg_waited_time = 0;
//平均帶權(quán)周轉(zhuǎn)時(shí)間
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;
}
//計(jì)算均值
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)時(shí)間:%05.2f平均等待時(shí)間:%05.2f平均帶權(quán)周轉(zhuǎn)時(shí)間:%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ùn)行的作業(yè) 
job * running_job = NULL;

//后備隊(duì)列不為空 或 就緒隊(duì)列不為空 或 正在有作業(yè)運(yùn)行  則進(jìn)行調(diào)度 
while (!is_queue_empty(created_queue)||!is_queue_empty(ready_queue)||running_job!=NULL)
{
    //把后備隊(duì)列中倡勇,到達(dá)時(shí)間為當(dāng)前系統(tǒng)時(shí)間的作業(yè)掛入就緒隊(duì)列
    while (!is_queue_empty(created_queue))
    {
        job * front_job = peek_queue(created_queue);
        if (front_job->arrival_time==current_time)
        {
            //后備隊(duì)列出隊(duì)一個作業(yè)并掛入就緒隊(duì)列
            en_queue_node(ready_queue,de_queue(created_queue) );
        }
        else
        {
            //一定要有else逞刷,表示后備隊(duì)列中的當(dāng)前隊(duì)頭作業(yè)的到達(dá)系統(tǒng)時(shí)間大于系統(tǒng)當(dāng)前時(shí)間,需要退出while循環(huán) 
            break;
        }
        
    }
    
    //判斷當(dāng)前是否有進(jìn)程使用CPU
    if (running_job == NULL)
    {
        //無作業(yè)使用CPU译隘,將就緒隊(duì)列隊(duì)頭出隊(duì)亲桥,去使用CPU
        if (!is_queue_empty(ready_queue))
            running_job = de_queue(ready_queue);
        else
        {
            //為了增加程序的健壯性,可以用某些其它數(shù)據(jù)測試(本題目要求沒有出現(xiàn)這種情況)
            //需要考慮固耘,當(dāng)前就緒隊(duì)列為空题篷,但后備隊(duì)列仍舊有未到達(dá)系統(tǒng)的作業(yè),系統(tǒng)時(shí)間空轉(zhuǎn)1個時(shí)間片 
            printf("系統(tǒng)%d時(shí)刻就緒隊(duì)列空\n", current_time);
            current_time++;
            continue; 
            
        }
        //printf("調(diào)度新的作業(yè)使用CPU:%d\n",running_job->PID);
    } 
    else
    {
        //如果有作業(yè)正在使用CPU厅目,判斷其使用CPU時(shí)間是否已經(jīng)滿足其要求服務(wù)時(shí)間
        if (running_job->used_time_slice==running_job->require_time_slice) 
        {
            //該作業(yè)要求服務(wù)時(shí)間已滿足
             
            //記錄作業(yè)完成時(shí)間 
            running_job->ended_time = current_time;
            //將該作業(yè)掛入完成隊(duì)列
            en_queue_node(ended_queue,running_job);
            //計(jì)算并存儲各種時(shí)間
            record_job_time(running_job); 
            printf("調(diào)作業(yè)%d已完成番枚,完成時(shí)間:%d\n",running_job->PID,running_job->ended_time);
            //從就緒隊(duì)列調(diào)度新的作業(yè)使用CPU 
            if (!is_queue_empty(ready_queue))
                running_job = de_queue(ready_queue);
            else
                running_job = NULL;
        }
        else
        {
            //空實(shí)現(xiàn) 
        } 
    }
    
    //系統(tǒng)時(shí)間步進(jìn) 
    current_time++;
    //當(dāng)前正在運(yùn)行的作業(yè)的使用的時(shí)間片++ 
    if (running_job!=NULL)
        running_job->used_time_slice++;
}

printf("FCFS的調(diào)度信息:\n");
//打印該調(diào)度算法的各種時(shí)間的平均值 
print_average_value();

}

void sjf_jobs()
{
//請實(shí)現(xiàn)法严,SJF算法
}
void rr_jobs(int q)
{
//請實(shí)現(xiàn),時(shí)間片輪轉(zhuǎn)RR算法葫笼,傳入?yún)?shù)為時(shí)間片q的大小
}
void hrrn_jobs()
{
//請實(shí)現(xiàn) 深啤,最高響應(yīng)比優(yōu)先算法HRRN(非搶占),
}

//作業(yè)結(jié)點(diǎn)入隊(duì)
void en_queue_node(linked_queue * queue,job * en_queue_pcb_node)
{
//將傳入的Job作業(yè)結(jié)點(diǎn)入隊(duì)
if (is_queue_empty(queue)){
queue->front = en_queue_pcb_node;
queue->rear = en_queue_pcb_node;
}else{
//隊(duì)列非空路星,
queue->rear->next = en_queue_pcb_node;
queue->rear = en_queue_pcb_node;
}
}

//判斷隊(duì)列是否為空
int is_queue_empty(linked_queue * queue)
{
if ((queue->front==NULL)&&(queue->rear==NULL))
return TRUE;
else
return FALSE;
}

/遍歷隊(duì)列溯街,按順序?qū)㈥?duì)列中每個元素的值打印輸出/
void show_queue_all_job(linked_queue * queue){
if (is_queue_empty(queue)){
printf("隊(duì)列為空,遍歷結(jié)束\n");
return;
}
//游標(biāo)指針
job * cursor_pcb_pointer;
cursor_pcb_pointer = queue->front;
printf("---------------\n");
printf("隊(duì)列為:\n");
/順序遍歷隊(duì)列每個結(jié)點(diǎn)/
while (cursor_pcb_pointer!=NULL){
//打印當(dāng)前結(jié)點(diǎn)信息洋丐,
printf("結(jié)點(diǎn)PID:%d呈昔,時(shí)間片需求為:%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("隊(duì)列為空,無法出隊(duì)\n");
return NULL;
}

return_job = queue->front;
if (queue->front==queue->rear){
    //只有一個結(jié)點(diǎn)時(shí)候
    queue->front=queue->rear=NULL;
}else{
    //多于一個結(jié)點(diǎn)時(shí)
    queue->front = queue->front->next;  
}
return_job->next = NULL;
return return_job;

}
//返回隊(duì)頭作業(yè)友绝,但不出隊(duì)
job * peek_queue(linked_queue * queue)
{
return queue->front;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堤尾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子迁客,更是在濱河造成了極大的恐慌郭宝,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掷漱,死亡現(xiàn)場離奇詭異粘室,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)切威,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門育特,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人先朦,你說我怎么就攤上這事缰冤。” “怎么了喳魏?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵棉浸,是天一觀的道長。 經(jīng)常有香客問我刺彩,道長迷郑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任创倔,我火速辦了婚禮嗡害,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘畦攘。我一直安慰自己霸妹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布知押。 她就那樣靜靜地躺著叹螟,像睡著了一般鹃骂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上罢绽,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天畏线,我揣著相機(jī)與錄音,去河邊找鬼良价。 笑死寝殴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的棚壁。 我是一名探鬼主播杯矩,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼栈虚,長吁一口氣:“原來是場噩夢啊……” “哼袖外!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起魂务,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤曼验,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后粘姜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鬓照,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年孤紧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豺裆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡号显,死狀恐怖臭猜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情押蚤,我是刑警寧澤蔑歌,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站揽碘,受9級特大地震影響次屠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雳刺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一劫灶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掖桦,春花似錦本昏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽紊馏。三九已至,卻和暖如春蒲犬,著一層夾襖步出監(jiān)牢的瞬間朱监,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工原叮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赫编,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓奋隶,卻偏偏與公主長得像擂送,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唯欣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348