實驗一 進程調度
一、實驗目的
編寫並調試一個模擬的進程調度程序,以加深對進程的概念及進程調度算法的理解.
二、實驗內容
- 調試運行“短進程優先”調度算法,給出運行結果。
- 采用“短進程優先”調度算法對五個進程進行調度。每個進程有一個進程控制塊( PCB)表示。進程控制塊可以包含如下信息:進程名、到達時間、需要運行時間、已用CPU時間、進程狀態等等。
- 每個進程的狀態可以是就緒 W(Wait)、運行R(Run)、或完成F(Finish)三種狀態之一。 每進行一次調度程序都打印一次運行進程、就緒隊列、以及各個進程的 PCB,以便進行檢查。重復以上過程,直到所要進程都完成為止。
三、實現思路
1. 變量聲明與結構體定義
2. 輸入函數
3. 所有進程結束后,輸出所有進程信息
4. 找出運行時間最短的進程
5. 進程執行完畢
6. 主函數
四、主要的數據結構
1. 變量聲明與結構體定義
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct pcb{
char name[10]; //進程名
int arrival_time; //進程到達時間()
int start_time; //進程開始時間
int need_time; //進程運行所需時間
int finish_time; //運行結束時間
struct pcb * link; //鏈接下一個pcb的指針
};
int num = 0; //輸入的進程數
typedef struct pcb PCB; //定義結構體變量
/*
結構體指針p指向 每新建的一個進程
ready指針指向鏈表的第一個pcb
finish指針指向完成隊列的第一個pcb結構體
*/
struct pcb *p = NULL, *ready = NULL, *finish = NULL;
2. 輸入函數
//用來測試鏈表建立,輸入鏈表結構體數據
void print_test(){
int i;
struct pcb * test = ready;
for(i=0;i<num;i++){
printf("\n進程號:%d,進程名:%s,進程到達時間:%d,進程完成時間:%d",
i,test->name,test->arrival_time,test->need_time);
if(NULL != test->link){
test = test->link;
}
else{
printf("\ntest_link end\n");
}
}
}
//輸入函數,建立鏈表
void input(){
int i;
struct pcb * q; //定義結構體變量
printf("請輸入進程數:");
scanf("%d", &num);
for(i=0; i<num; i++){
printf("\n進程號 NO.%d:", i);
p = (struct pcb*)malloc(sizeof(struct pcb));
printf("\n輸入進程名:");
scanf("%s", p->name);
printf("\n請輸入進程到達時間:");
scanf("%d", &p->arrival_time);
printf("\n請輸入進程運行時間:");
scanf("%d", &p->need_time);
p->link = NULL;
//建立鏈表
if(NULL == ready){ //建立第一個結構體,使指針p,q指向它
ready = p;
q = ready;
}
else{ //鏈表建立
q->link = p;
q = p;
}
printf("input success");
}
print_test(); //測試鏈表是否建立
}
3.所有進程結束后,輸出所有進程信息
//輸出當前運行進程相關數據或者打印暫無進程運行
void output(struct pcb * p, int now_time){
if(NULL == p){
printf("當前時刻:%d, 暫無進程在運行!\n", now_time);
}
else{
printf("進程名:%s,到達時間:%d,運行需要時間:%d\n",p->name,p->arrival_time,p->need_time);
}
}
- 4. 找出運行時間最短的進程
//sjf shortest job first最短作業優先
struct pcb * SJF(int now_time, int * after){
int min_time = 0; //最短時間,即優先運行的進程的時間
struct pcb * now_progress = NULL, *p = ready;
//遍歷鏈表,查找出運行時間最短的進程
if (NULL != ready){
while(NULL != p){
if(now_time >= p->arrival_time){ //若進程已經到達,注意:時間單位為1
/*
min_time = p->need_time; //是錯誤的
now_progress = p;
if(p->need_time < min_time){
min_time = p->need_time;
now_progress = p;
} */
if(0 == min_time){ //給最短時間賦初值
now_progress = p;
min_time = p->need_time;
}
else{
if(p->need_time < min_time){
now_progress = p;
min_time = p->need_time;
}
}
}
p = p->link;
}
}
*after = min_time + now_time;
printf("\nSJF:a shortest progress running!\n");
return now_progress; //返回指向正在運行進程的指針
}
5. 進程執行完畢
//將已經運行完成的進程添加到finish隊列,並且進程數減一
void destory(struct pcb * p, int now_time){
printf("destory start!\n");
struct pcb * q = ready;
struct pcb * f = NULL; //用於finish鏈表的添加
if(strcmp(p->name, ready->name) == 0){ //若第一個進程完成
ready = ready->link;
}
//若中間或最后一個進程完成
else{
q = ready;
while((strcmp(q->link->name,p->name) != 0) && NULL != q->link){
q = q->link;
}
q->link = p->link;
}
p->finish_time = now_time; //結束時間
p->start_time = now_time - p->need_time; //開始時間
//將已經運行的進程添加到finish隊列
if(NULL == finish){
finish = p; //finish指向完成鏈表的表頭
p->link = NULL;
}
else{
f = finish;
while(NULL != f->link){
f = f->link;
}
f->link = p;
p->link = NULL;
}
num--; //進程數減一
printf("\ndestory success!\n");
}
主函數
int main(int argc, char *argv[]) {
input(); //調用輸入函數
int now_time = 0; //初始時間為0
int after = 0; //執行完一個進程后的時間:優先運行進程的運行時間+當前時間
struct pcb * now_progress = NULL; //now_progress指向正在運行的進程(結構體)
struct pcb *m = NULL;
while(num > 0){ //進程數大於0,每次循環num會減一
printf("start SJF");
now_progress = SJF(now_time, &after); //調用SJF函數,遍歷鏈表
if(NULL != now_progress){
/*進程執行,每循環一次,當前時間加一
同時要判斷當前時間是否有進程剛好到達正在在等待 */
for(;now_time < after; now_time++){
printf("\n當前時刻:%d", now_time);
printf("\n-----------當前執行進程------------\n");
output(now_progress, now_time); //調用output函數
printf("\n-----------等待執行進程------------\n");
m = ready;
while(NULL != m){ //循環,若當前時間有進程到達,打印相關信息
if(m != now_progress){
if(m->arrival_time <= now_time){
output(m, now_time);
printf("\na new progress arrival\n");
}
}
m = m->link;
}
}
//進程執行完后調用destory函數
destory(now_progress, now_time);
}
else{ //沒有進程在運行
output(now_progress, now_time);
now_time++;
}
}
output_all();
return 0;
}
五、算法流程圖
六、運行與測試(系統運行截圖)
七、總結
SJF算法是以進程的運行時間長度作為優先級,進程運行時間越短,優先級越高。
缺點
必須預知進程的運行時間。即使是程序員也很難准確估計進程運行時間。如果估計過低,系統就可能按估計的時間終止進程的運行,但此時進程並未完成,故一般都會偏長估計
對長進程不利。長進程的周轉時間會明顯地增長。可怕的是,SJF算法完全忽視進程等待時間,可能使進程等待時間過長,出現飢餓現象。
人機無法實現交互。
完全未考慮進程的緊迫程度。不能保證緊迫性進程得到及時處理。
問題:對比說明短進程優先和動態優先數中PCB的定義有什么不同?