进程调度模拟

操作系统原理实验——进程调度模拟实验报告

一、实验目的与要求:

(1)本实验目的是通过对进程调度算法的实现和实验模拟,加深对操作系统进程调度操作功能和进程调度算法的完整理解,培养和提高学生对操作系统开发的兴趣,以及进程调度程序的开发与应用能力;

(2)理论上必须深刻理解优先权调度算法和时间片轮转调度算法的基本思想和原理;

(3)独立使用C、C++或Java编程语言编写优先权调度或时间片轮转算算法调度模拟程序;

(4)按照实验题目要求独立正确地完成实验内容(编写、调试算法程序,提交程序清单及及相关实验数据与运行结果)

二、实验内容及说明

(1)设计有5个进程并发执行的模拟调度程序,每个程序由一个PCB表示。PCB的结构如下所示:

PCB中各项说明:

id:进程编号,范围1~5;

cputime:已经运行的时间片数;

alltime:剩下还需要运行的时间片数;

startblock:运行进程运行startblock个时间片后开始阻塞;

blocktime:阻塞进程在经过blocktime后解除阻塞(恢复成就绪状态);

state:进程状态,可以是ready、run、block和finish其中之一;

next:指向队列中下一个PCB的指针(或索引)

id

cputime

alltime

startblock

blocktime

state

next

(2)模拟调度程序可任选两种调度算法之一实现(有能力的同学可同时实现两个调度算法)。

(3)程序执行中应能在屏幕上显示出各进程的状态变化,以便于观察调度的整个过程。

(4)本次实验内容(项目)的详细说明以及要求请参见实验指导书。

    

三、主要实验步骤说明

(1)创建并初始化PCB队列:先创建每一个PCB,要求第1项id的值依据创建先后顺序分别赋值为1~5,第2~5项的值可以随机产生(例如0~5范围内的一个随机整数),第6项的初始状态是ready。创建的各PCB要通过next域连接到Ready队列中,而队列的组织则要依据调度算法的要求来决定:如果是SPF(短进程优先)调度算法,要求Ready队列中的各PCB按照alltime的值由小到大依次排列;而对于RR(时间片轮转)或FCFS(先来先服务)调度算法则可以按照id号由小到大依次排列。

(2)初始化后,把Ready队列的队首进程取出,并放入Run队列中,相应修改Run队列中的该进程的state为run状态,表示该进程准备投入运行;用于存放阻塞进程的Block队列以及表示运行结束的Finish队列初始都为空。

(3)运行时以时间片作为基本的时间单位(时间片可以由一个单独的变量time来表示),每经过一个时间片,需要做如下处理:

①对于Run队列中的进程:cputime+1,alltime-1,startblock-1;对于Block队列中的进程:blocktime-1(而对于Ready队列中的各进程不需要处理)

②当上述处理结束后,可能需要重新调整队列,并判断是否需要重新调度CPU,以便为下一个时间片的运行做好准备:

a.对于Block队列中所有blocktime值等于0的进程(表示这些进程已经阻塞完成),需要把它们放入的Ready队列的适当位置:对于RR算法,直接把这些进程依次插入到Ready队列的队尾,而对于SPF算法,则需要依据这些进程各自alltime值的大小插入到Ready队列的适当位置。

b.而对于Run队列中的进程,如果其alltime值等于0,则表示它已经运行完成,需要把它放入Finish队列,并重新调度(所谓重新调度,当然就是让Ready队列队首进程投入运行);否则,如果其startblock值等于0,则表示已经到达阻塞时间,需要把它放入Block队列,并重新调度;否则,要根据调度算法决定其是否可以继续运行:在RR算法中,直接把该运行进程插入到Ready队列的队尾,重新调度;在SPF算法中,需要把当前运行进程的alltime值与当前Ready队列队首进程的alltime值比较,如果前者的alltime值更小,则当运行进程可以继续保持运行状态(在下一个时间片继续处于Run队列中),而如果后者的alltime值更小,则需要把当前运行进程(按照其alltime值的大小)插入到Ready队列的适当位置,并重新调度。

③打印出三个队列(Ready、Run和Block)中各进程的状态

(4)当Run队列不为空时,继续进行下一个时间片的处理,直到Run队列为空为止(即所有进程运行结束),整个调度程序终止运行。

四、程序流程图

五、主要程序清单

RR算法

#include <stdio.h>

#include <queue>

#define num 6

typedef struct {

    int id;

    int cputime;

    int alltime;

    int starttime;

    int blocktime;

    int state;

    int next;

}RRProject;

typedef struct {

    RRProject P[num];

    int front, rear;

}Queue;

void initQueue(Queue* queue) {

    queue->front = 0;

    queue->rear = 0;

}

//入队

void enqueue(Queue* queue, RRProject process) {

    // 判断队列是否已满

    if ((queue->rear + 1) % num == queue->front) {

        return;

    }

    queue->P[queue->rear] = process;

    queue->rear = (queue->rear + 1) % num;

}

//出队

RRProject dequeue(Queue* queue) {

    // 判断队列是否为空

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

        RRProject emptyProcess = { 0 }; // 返回一个空的 RRProject 结构体

        return emptyProcess;

    }

    RRProject process = queue->P[queue->front];

    queue->front = (queue->front + 1) % num;

    return process;

}

//初始化Ready

void init(Queue *Q) {

    RRProject RR[num];

    for (int i = 0; i < num; i++) {

        RR[i].id = i + 1;

        RR[i].cputime = 0;

        RR[i].state = 1;

    }

    RR[0].alltime = 3;

    RR[0].starttime = 2;

    RR[0].blocktime = 1;

    RR[0].next = 2;

    RR[1].alltime = 2;

    RR[1].starttime = 1;

    RR[1].blocktime = 2;

    RR[1].next = 3;

    RR[2].alltime = 5;

    RR[2].starttime = 3;

    RR[2].blocktime = 2;

    RR[2].next = 4;

    RR[3].alltime = 2;

    RR[3].starttime = 1;

    RR[3].blocktime = 3;

    RR[3].next = 5;

    RR[4].alltime = 4;

    RR[4].starttime = 2;

    RR[4].blocktime = 1;

    RR[4].next = 0;

    for (int i = 0; i < num; i++) {

        enqueue(Q, RR[i]);

    }

}

//打印

void printData(Queue Q){

    int i = Q.front;

    while (i != Q.rear) {

        printf("%d", Q.P[i].id);

        printf("\t%d", Q.P[i].cputime);

        printf("\t%d", Q.P[i].alltime);

        printf("\t%d", Q.P[i].starttime);

        printf("\t%d", Q.P[i].blocktime);

        if (Q.P[i].state == 0){

            printf("\tFinish");

        }

        else if (Q.P[i].state == 1){

            printf("\tReady");

        }

        else if (Q.P[i].state == 2){

            printf("\tRun");

        }

        else if (Q.P[i].state == 3) {

            printf("\tBlock");

        }

        printf("\t%d \n", Q.P[i].next);

        i = (i + 1) % num;

    }

}

void operate(RRProject *RR) {

    RR->alltime--;

    RR->cputime++;

    RR->starttime--;

    RR->next = 0;

}

int main() {

    Queue Ready,Run,Finish,Block;

    initQueue(&Ready);

    initQueue(&Run);

    initQueue(&Finish);

    initQueue(&Block);

    init(&Ready);

    printf("初始:\n");

    printf("id     cpu     all    start   block    state   next\n");

    printData(Ready);

    while ((Finish.rear + 1) % num != Finish.front) {

        printf("\n一个时间段开始:\n");

        enqueue(&Run, Ready.P[Ready.front]);

        dequeue(&Ready);

        Run.P[Run.front].state = 2;

        Run.P[Run.front].next = 0;

        printf("id     cpu     all    start   block    state   next\n");

        printData(Run);

        printData(Ready);

        printData(Block);

        operate(&Run.P[Run.front]);

        if (Run.P[Run.front].alltime == 0) {

            Run.P[Run.front].state = 0;

        }

        else if (Run.P[Run.front].starttime == 0) {

            Run.P[Run.front].state = 3;

        }

        else {

            Run.P[Run.front].state = 1;

        }

        if (Run.P[Run.front].state == 0) {

            if (Finish.rear != Finish.front)

            {

                Finish.P[(Finish.rear - 1 + num) % num].next = Run.P[Run.front].id;

            }

            enqueue(&Finish, Run.P[Run.front]);

        }

        else if (Run.P[Run.front].state == 1) {

            if (Ready.rear != Ready.front) {

                Ready.P[(Ready.rear - 1 + num) % num].next = Run.P[Run.front].id;

            }

            enqueue(&Ready, Run.P[Run.front]);

        }

        else if (Run.P[Run.front].state == 3) {

            if (Block.rear != Block.front) {

                Block.P[(Block.rear - 1 + num) % num].next = Run.P[Run.front].id;

            }

            enqueue(&Block, Run.P[Run.front]);

        }

        int r = Block.front;

        while (r != Block.rear&& Run.P[Run.front].id != Block.P[r].id) {

            Block.P[r].blocktime--;

            if (Block.P[r].blocktime == 0) {

                Block.P[Block.front].state = 1;

                if (Ready.rear != Ready.front) {

                    Ready.P[(Ready.rear - 1 + num) % num].next = Block.P[Block.front].id;

                }

                Block.P[r].next = 0;

                enqueue(&Ready, Block.P[r]);

                dequeue(&Block);

            }

            r = (r + 1) % num;

        }

        dequeue(&Run);

    }

    return 0;

}

SPF算法

#include <stdio.h>

#include <queue>

#define num 6

typedef struct {

    int id;

    int cputime;

    int alltime;

    int starttime;

    int blocktime;

    int state;

    int next;

}RRProject;

typedef struct {

    RRProject P[num];

    int front, rear;

}Queue;

void initQueue(Queue* queue) {

    queue->front = 0;

    queue->rear = 0;

}

int size(Queue* Q) {

    int length = 0;

    int  i = Q->front;

    while (i != Q->rear) {

        length++;

        i = (i + 1) % num;

    }

    return length;

}

//入队

void enqueue(Queue* queue, RRProject process) {

    // 判断队列是否已满

    if ((queue->rear + 1) % num == queue->front) {

        return;

    }

    queue->P[queue->rear] = process;

    queue->rear = (queue->rear + 1) % num;

}

void entry(Queue* queue, RRProject process) {

    // 判断队列是否已满

    if ((queue->rear + 1) % num == queue->front) {

        return;

    }

    queue->P[queue->front-1] = process;

    queue->front = (queue->front - 1+ 5) % 5;

}

//出队

RRProject dequeue(Queue* queue) {

    // 判断队列是否为空

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

        RRProject emptyProcess = { 0 }; // 返回一个空的 RRProject 结构体

        return emptyProcess;

    }

    RRProject process = queue->P[queue->front];

    queue->front = (queue->front + 1) % num;

    return process;

}

void sort(Queue* Q) {

    int length = size(Q);

    for (int i = 0; i < length; i++) {

        for (int j = i; j < length; j++) {

            if (Q->P[i].alltime  > Q->P[j].alltime ) {

                RRProject temp = Q->P[i];

                Q->P[i] = Q->P[j];

                Q->P[j] = temp;

            }

        }

    }

    for (int i = 0; i < length; i++) {

        Q->P[i].next = Q->P[i + 1].id;

    }

    Q->P[Q->rear - 1].next = 0;

}

//初始化Ready

void init(Queue* Q) {

    RRProject RR[num];

    for (int i = 0; i < num; i++) {

        RR[i].id = i + 1;

        RR[i].cputime = 0;

        RR[i].state = 1;

    }

    RR[0].alltime = 3;

    RR[0].starttime = 2;

    RR[0].blocktime = 1;

    RR[0].next = 2;

    RR[1].alltime = 2;

    RR[1].starttime = 1;

    RR[1].blocktime = 2;

    RR[1].next = 3;

    RR[2].alltime = 5;

    RR[2].starttime = 3;

    RR[2].blocktime = 2;

    RR[2].next = 4;

    RR[3].alltime = 2;

    RR[3].starttime = 1;

    RR[3].blocktime = 3;

    RR[3].next = 5;

    RR[4].alltime = 4;

    RR[4].starttime = 2;

    RR[4].blocktime = 1;

    RR[4].next = 0;

    for (int i = 0; i < num; i++) {

        enqueue(Q, RR[i]);

    }

}

//打印

void printData(Queue Q) {

    int i = Q.front;

    while (i != Q.rear) {

        printf("%d", Q.P[i].id);

        printf("\t%d", Q.P[i].cputime);

        printf("\t%d", Q.P[i].alltime);

        printf("\t%d", Q.P[i].starttime);

        printf("\t%d", Q.P[i].blocktime);

        if (Q.P[i].state == 0) {

            printf("\tFinish");

        }

        else if (Q.P[i].state == 1) {

            printf("\tReady");

        }

        else if (Q.P[i].state == 2) {

            printf("\tRun");

        }

        else if (Q.P[i].state == 3) {

            printf("\tBlock");

        }

        printf("\t%d \n", Q.P[i].next);

        i = (i + 1) % num;

    }

}

void operate(RRProject* RR) {

    RR->alltime--;

    RR->cputime++;

    RR->starttime--;

    RR->next = 0;

}

int main() {

    Queue Ready, Run, Finish, Block;

    initQueue(&Ready);

    initQueue(&Run);

    initQueue(&Finish);

    initQueue(&Block);

    init(&Ready);

    printf("初始:\n");

    printf("id     cpu     all    start   block    state   next\n");

    printData(Ready);

    sort(&Ready);

    while ((Finish.rear + 1) % num != Finish.front) {

        printf("\n一个时间段的开始:\n");

        if (Run.front == Run.rear && Ready.front != Ready.rear) {

            enqueue(&Run, Ready.P[Ready.front]);

            dequeue(&Ready);

            Run.P[Run.front].state = 2;

        }

        else if (Run.P[Run.front].alltime > Ready.P[Ready.front].alltime && Ready.front != Ready.rear) {

                RRProject temp = Run.P[Run.front];

                Run.P[Run.front] = Ready.P[Ready.front];

                Ready.P[Ready.front] = temp;

                Ready.P[Ready.front].next = Ready.P[(Ready.front+1)%num].id;

                Ready.P[Ready.front].state = 1;

                Run.P[Run.front].next = 0;

                Run.P[Run.front].state = 2;

        }

        Run.P[Run.front].next = 0;

        printf("id     cpu     all    start   block    state   next\n");

        printData(Run);

        printData(Ready);

        printData(Block);

        if (Run.front != Run.rear) {

            operate(&Run.P[Run.front]);

            if (Run.P[Run.front].alltime == 0) {

                Run.P[Run.front].state = 0;

            }

            else if (Run.P[Run.front].starttime == 0) {

                Run.P[Run.front].state = 3;

            }

            if (Run.P[Run.front].state == 0) {

                if (Finish.rear != Finish.front) {

                    Finish.P[(Finish.rear - 1 + num) % num].next = Run.P[Run.front].id;

                }

                enqueue(&Finish, Run.P[Run.front]);

            }

            else if (Run.P[Run.front].state == 3) {

                if (Block.rear != Block.front) {

                    Block.P[(Block.rear - 1 + num) % num].next = Run.P[Run.front].id;

                }

                enqueue(&Block, Run.P[Run.front]);

            }

        }

        int r = Block.front;

        while ((r != Block.rear) && (Run.P[Run.front].id != Block.P[r].id)) {

            Block.P[r].blocktime--;

            if (Block.P[r].blocktime == 0) {

                Block.P[Block.front].state = 1;

                if (Ready.front != Ready.rear) {

                    Block.P[r].next = Ready.P[Ready.front].id;

                    entry(&Ready, Block.P[r]);

                  

                }else {

                    enqueue(&Ready, Block.P[r]);

                }

                dequeue(&Block);

            }

            r = (r + 1) % num;

        }

        if(Run.P[Run.front].state != 2)

            dequeue(&Run);

    }

    return 0;

六、程序运行结果与分析

RR算法

SPF算法

七、实验体会

完成这个实验,让我对RR算法和SPF算法有了更深的理解。通过实际编写代码和测试的过程,我深刻体会到了这两种调度算法的优势和局限性。RR算法作为一种公平调度算法,在多任务环境下能够保证每个就绪进程都有机会被执行。通过设置时间片,可以有效避免长时间运行的进程霸占CPU资源,确保其他进程也能得到执行。然而,由于时间片的限制,长时间运行的进程可能需要较长的等待时间才能完成,这可能会对响应时间产生一定的影响。SPF算法则注重最小化平均等待时间,通过选择执行时间最短的进程来提高系统的响应速度。这在短作业或交互式应用程序的场景下特别有效。然而,SPF算法也存在优先级反转问题,即长作业可能会阻塞短作业的执行,从而影响系统的整体性能。通过这次实验,我意识到在实际应用中,选择适当的调度算法非常重要。需要根据任务类型、系统需求和性能目标来权衡各种因素。有时候公平性更重要,选择RR算法;有时候追求响应速度更为关键,那就选择SPF算法。在实际应用中,这两种算法也可以结合使用,根据实际情况动态调整调度策略。这次实验让我深入了解了RR算法和SPF算法,并认识到调度算法选择对系统性能和用户体验具有重要影响。对于未来的工作和研究,我将进一步学习和探索其他调度算法,以便能够更好地应对不同的任务和需求。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值