时间片轮转——进程调度

原创


上一篇博客写了最高优先级算法——进程调度:http://www.cnblogs.com/chiweiming/p/9028002.html

此篇介绍时间片轮转调度,时间片轮转调度比最高优先级调度更为简单,每次都从PCB(进程存在的唯一标识)队列中将

首进程调入CPU,增加其已用CPU时间,改变其进程状态;然后判断其已用CPU时间是否大于等于需要运行时间,大于将

其进程状态置为完成状态,否则将此PCB插入队列尾部,再次在队列中寻找优先级最高的PCB...两篇博客的代码大同小异。

/*
    时间片轮转算法 
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 3
#define Time_film 2    //时间片

int count = 0;

void print(struct PCB *head);

struct PCB{
    int process_name;    //进程名 
    int priority_number;    //优先数,全置0 
    int arrive_time;    //到达时间,为进程的创建时间
    int need_time;    //需要运行的时间,随机产生
    int used_time;    //已用CPU的时间,初始值为0
    int process_state;    //进程状态,1表示运行,0表示完成,-1表示就绪,初始值为-1 
    struct PCB *cre;    //前驱指针域
    struct PCB *next;    //后驱指针域
};

void Process_scheduling(struct PCB *head){
    /*
    扫描队列,将进程按到底顺序调入CPU运行;
    如果 use_CPU == need_time 撤销此PCB; 
    否则用完一个时间片后放回队列尾部,继续扫描;
    */
    //****************************
    struct PCB *Move=head;
    struct PCB *Max_Pri=head->next;
    struct PCB *Tail;    //尾指针 
    //****************************
    Move->next = Max_Pri->next;        //调出队列首进程
    if(Move->next != NULL){
        Move = Max_Pri->next;
        Move->cre = Max_Pri->cre;
    }
    //****************************
    printf("        进程 %d 被调度: 
",Max_Pri->process_name);
    Max_Pri->used_time += Time_film;    //增加CPU占用时间
    if(Max_Pri->used_time >= Max_Pri->need_time){
        Max_Pri->used_time = Max_Pri->need_time;    //进程状态改变
        Max_Pri->process_state = 0;
        count++;
    }
    else{
        Max_Pri->process_state = 1;
    }
    printf(" %d     %d     %d        %d         %d      %d 

",Max_Pri->process_name,Max_Pri->priority_number,Max_Pri->arrive_time,Max_Pri->need_time,Max_Pri->used_time,Max_Pri->process_state);
    if(count == N){    //所有进程执行完毕 
        printf("        所有进程执行完毕!");
        return;
    }
    printf("        就绪队列:
");
    print(head);    //输出就绪队列
    printf("
");
    //****************************
    if(Max_Pri->process_state !=0){
        Move = head;
        while( Move->next!=NULL ){    //当被调出进程未完成时将其插入就绪队列尾部 
            Move = Move->next; 
        }
        Tail = Move;
        Max_Pri->cre = Tail;
        Max_Pri->next = NULL;
        Tail->next = Max_Pri;
        Max_Pri->process_state = -1;
    }
    //****************************
    Process_scheduling(head);
}

void print(struct PCB *head){    //输出队列函数 
    if(head->next == NULL){
        printf("就绪队列已空
");
        return;
    }
    printf("name priority arr_time need_time use_CPU pro_state
");
    struct PCB *fry = head->next;
    while(fry != NULL){
        printf(" %d     ",fry->process_name);
        printf("%d     ",fry->priority_number);
        printf("%d        ",fry->arrive_time);
        printf("%d         ",fry->need_time);
        printf("%d      ",fry->used_time);
        printf("%d ",fry->process_state);
        printf("
");
        fry = fry->next;    
    }
    printf("
"); 
}

int main(){
    struct PCB *head;    //头指针
    struct PCB Pro[N+1];    //创建 N+1 个进程
    head = &Pro[0];
    srand(time(0));
    
    //****************************
    //设置进程参数
    Pro[0].process_name = 0;
    Pro[0].cre = NULL;
    Pro[0].next = &Pro[1];
    Pro[0].priority_number = 0;
    int i=0;
    for(i=1;i<=N;i++){
        Pro[i].process_name = i;
        Pro[i].priority_number = 0;
        Pro[i].arrive_time = i;
        Pro[i].need_time = rand()%7;
        while(Pro[i].need_time == 0){
            Pro[i].need_time = rand()%7;
        }
        Pro[i].used_time = 0;
        Pro[i].process_state = -1;
    }
    for(i=1;i<=N;i++){    //形成双向队列
        if( i == N ){
            Pro[i].cre = &Pro[i-1];
            Pro[i].next = NULL;
            break;
        }
        Pro[i].cre = &Pro[i-1];
        Pro[i].next = &Pro[i+1];
    }
    //****************************
    
    printf("        进程初始状态: 
");
    print(head);    //输出初始队列状态
    
    Process_scheduling(head);    //调用进程调度函数(时间片轮转)
    return 0;
} 

(运行结果部分截图)

15:52:07

2018-05-13

改进:

上面忽视了进程的到达时间这个因素,会产生这样的错误:

执行了当前进程,但是下一进程未到达,确仍被执行。

创建进程时对进程时间由小到大的赋值;每次从已经到达的进程中顺序选择进程调入CPU运行,可以设置一个动态的系统时间

system_time(初始值为最先到达进程的到达时间)system_time在每个进程执行完一次后都增加该进程次执行的时间(这

不指明每次执行时间为时间片是因为当进程剩下需要的执行时间小于一个时间片后system_time不会增加一个时间片),进程每

次执行完一个时间片后,将 system_time每个进程的到达时间进行比较,大于system_time则未到达,反之,;每个进程

执行完一个时间片后判断是否执行完毕,执行完毕则撤销,否则将其插入队列尾部;下次再从队列首部开始顺序查找,队列扫描

指针指向的进程的到达时间若小于等于system_time则将其调出执行......值得一提的是,若遇进程到来比较晚即前面的进程都已

执行完成(已从队列中移除),则通过system_time将找不到合适的进程调入,此时必须通过 “手动”加系统时间来达到下一个

进程的到达时间,然后将其执行。

/*
    时间片轮转算法 
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 5
#define Time_film 2    //时间片

int count = 0;    //统计进程完成个数 
int system_time=100; 
int flag=0;
int ff=0;

void print(struct PCB *head);

struct PCB{
//    int fl;
    int process_name;    //进程名
    int priority_number;    //优先数,随机产生 
    int arrive_time;    //进程的到达时间,随机产生 
    int need_time;    //需要运行的时间,随机产生 
    int used_time;    //已用CPU的时间,初始值为0 
    int process_state;    //进程状态,1表示运行,0表示完成,-1表示就绪,初始值为-1 
    struct PCB *cre;    //前驱指针域
    struct PCB *next;    //后驱指针域
};

void Process_scheduling(struct PCB *head){
    /*
    扫描队列,将最先到达的进程调入运行,于运行状态
    的进程用完一个时间片后判断进程是否执行完毕,完毕 
    则撤销,否则插入队列尾部,再从头扫描队列,寻找
    已经到达的进程。 
    */
     
    //****************************
    struct PCB *Move=head->next;
    struct PCB *Max_Pri=head;
    struct PCB *Tail;    //尾指针 
    //****************************
    flag=0;
    ff=0;
    while(++flag){
        Move=head->next;
        Max_Pri=head;
        while(Move!=NULL){    //每次从队列头部开始扫描,取出已到达进程即可
            if(Move->arrive_time<=system_time){
                Max_Pri=Move;
                break;
            }
            Move=Move->next;
        }
        if(Max_Pri->cre==NULL){    //说明当前没有到达进程 
            ff=1;
            system_time++;    //增加系统时间 
        }
        else{
            break;
        }
        
    }
    if(ff==1){
        printf("暂无进程可执行,等待 %d 后,系统时间为: %d 

",flag-1,system_time);
    }
    /*
    Move=hear->next;
    while(Move!=NULL){    //在几个同时最早时间到达的进程中选择优先级最高的 
        if(Max_Pri->arrive_time == Move->arrive_time){
            if(Max_Pri->priority_number>Move->priority_number){
                Max_Pri=Move;
            }
        }
        Move=Move->next;
    }
    */
    /*
    while(++flag){
        Move=head->next;
        Max_Pri=head;
        while(Move!=NULL){
            if(Move->arrive_time < system_time){    //小于等于系统时间的进程说明已经到达
                Max_Pri=Move;
            }
            Move=Move->next;
        }
        if(Max_Pri->cre==NULL){    //说明没有选出合适进程,需要增加系统时间
            printf("暂无进程可执行,等待 %d 后~
",flag-2);
            system_time++;
        }
        else{
            break;
        }
    }
    */
    //****************************
    Move = Max_Pri->cre;        //将上面选择的进程调入CPU运行
    Move->next = Max_Pri->next;
    if(Move->next != NULL){
        Move = Max_Pri->next;
        Move->cre = Max_Pri->cre;
    }
    //****************************
    printf("        进程 %d 被调度: 
",Max_Pri->process_name);
    Max_Pri->used_time += Time_film;    //增加CPU占用时间
    if(Max_Pri->used_time >= Max_Pri->need_time){
        if(Max_Pri->used_time==Max_Pri->need_time){
            system_time+=Time_film;
        }
        if(Max_Pri->used_time > Max_Pri->need_time){
            system_time+=(Max_Pri->used_time-Max_Pri->need_time);
        }
        Max_Pri->used_time = Max_Pri->need_time;
        Max_Pri->process_state = 0;        //进程状态改变
        count++;
    }
    else{
        system_time+=Time_film;
        Max_Pri->process_state = 1;
    }
//    Max_Pri->priority_number-=1;    //优先数减1
    printf(" %d     %d     %d        %d         %d       %d

",Max_Pri->process_name,Max_Pri->priority_number,Max_Pri->arrive_time,Max_Pri->need_time,Max_Pri->used_time,Max_Pri->process_state);
    if(count == N){    //所有进程执行完毕 
        printf("        所有进程执行完毕!");
        return;
    }
    if(Max_Pri->process_state==1){
        printf("进程 %d 未完成,进入就绪队列,系统时间为: %d 

",Max_Pri->process_name,system_time);
    }
    else{
        printf("进程 %d 已完成,系统时间为: %d 

",Max_Pri->process_name,system_time);
    }
    printf("        就绪队列:
");
    //****************************
    if(Max_Pri->process_state !=0){
        Move = head;
        while( Move->next!=NULL ){    //当被调出进程未完成时将其插入就绪队列尾部
            Move = Move->next; 
        }
        Tail = Move;
        Max_Pri->cre = Tail;
        Max_Pri->next = NULL;
        Tail->next = Max_Pri;
        Max_Pri->process_state = -1;
    }
    print(head);
    //****************************
    Process_scheduling(head);
}

void print(struct PCB *head){    //输出队列函数 
    if(head->next == NULL){
        printf("就绪队列已空
");
        return;
    }
    printf("name priority arr_time need_time use_CPU pro_state
");
    struct PCB *fry = head->next;
    while(fry != NULL){
        printf(" %d     ",fry->process_name);
        printf("%d     ",fry->priority_number);
        printf("%d        ",fry->arrive_time);
        printf("%d         ",fry->need_time);
        printf("%d      ",fry->used_time);
        printf("%d          ",fry->process_state);
        printf("
");
        fry = fry->next;
    }
    printf("
"); 
}

int main(){
    struct PCB *head;    //头指针
    struct PCB Pro[N+1];    //创建 N+1 个进程-----就绪状态队列
    srand(time(0));
    
    //****************************
    //设置就绪状态进程参数
    head = &Pro[0];
    int i=0;
    for(i=0;i<=N;i++){
        if(i==0){
            Pro[i].process_name = 0;
            Pro[i].cre = NULL;
            Pro[i].next = &Pro[i+1];
            Pro[i].priority_number = -100;
            Pro[i].arrive_time=-1;
//            Pro[i].fl=0;
            continue;
        }
        Pro[i].process_name = i;
        Pro[i].priority_number = rand()%10;
        while(Pro[i].priority_number == 0){
            Pro[i].priority_number = rand()%10;
        }
        
        Pro[i].arrive_time = rand()%(i+i*5);    //进程到达时间由小到大的创建 
        while(Pro[i].arrive_time<Pro[i-1].arrive_time){
            Pro[i].arrive_time=rand()%(i+i*5);
        }
        
        Pro[i].need_time = rand()%7;
        while(Pro[i].need_time == 0){
            Pro[i].need_time = rand()%7;
        }
        Pro[i].used_time = 0;
        Pro[i].process_state = -1;
//        Pro[i].fl=0;
    }
    for(i=1;i<=N;i++){    //形成双向队列
    
        if( i == N ){
            Pro[i].cre = &Pro[i-1];
            Pro[i].next = NULL;
            break;
        }
        Pro[i].cre = &Pro[i-1];
        Pro[i].next = &Pro[i+1];
    
        /*
        if(Pro[i].fl==0){    //0代表未被选中 
            if(Pro[i].arrive_time<min){
                min=Pro[i].arrive_time;
                p=&Pro[i].arrive_time;
            }    
        }
        */
        /*
        //****************************
        struct PCB *Move;
        struct PCB *Tail;
        Move = head;
        while( Move->next!=NULL ){    //指向尾元素 
            Move = Move->next; 
        }
        Tail = Move;
        p->cre = Tail;    //将选出的进程插入就绪队列
        p->next = NULL;
        Tail->next = p;
        //****************************
        */
    }
    //****************************
    for(i=1;i<=N;i++){    //将最先到达进程的时间设置为系统开始时间 
        if(Pro[i].arrive_time<system_time){
            system_time=Pro[i].arrive_time;
        }
    }
    printf("系统时间为: %d 
",system_time);
    //****************************
    
    printf("        就绪状态进程: 
");
    print(head);    //输出就绪状态进程
    
    Process_scheduling(head);    //调用进程调度函数(时间片轮转)
    
    return 0;
}

(运行结果部分截图)

17:07:17

2018-05-18

原文地址:https://www.cnblogs.com/chiweiming/p/9032385.html