操作系统---进程调度算法实现

本次实现的是模拟在单处理器情况下的处理器调度,目的是设计一个按优先数调度算法实现处理器调度的程序。

内容

(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
这里写图片描述

  • 进程名——作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。

  • 指针——按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。

  • 要求运行时间——假设进程需要运行的单位时间数。

  • 优先数——赋予进程的优先数,调度时总是选取优先数大的进程先执行。

  • 状态——可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。

(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。
(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例:
这里写图片描述

(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:

优先数-1
要求运行时间-1
来模拟进程的一次运行。

提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。

(5) 进程运行一次后,若要求运行时间0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它的状态修改成“结束”(E),且退出队列。
(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。
(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。
(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。

算法流程图

这里写图片描述

代码及演示结果

#include <stdio.h>                                                                                                     
#include <malloc.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <string.h>
#define NAMEMAX 64
#define PROCMAX 64
typedef enum Status{
    R,                 //就绪
    E                  //结束
}Status;
typedef struct Proc{
    char name[NAMEMAX];//进程名
    char next[NAMEMAX];//下一个需要调度的进程的名字
    size_t run_time;   //要求运行时间
    int prio_num;      //优先数
    Status status;     //状态
}Proc;

typedef struct ProcQueue{//进程队列结构体
    Proc* data;          //指向在堆上动态开辟的内存空间,用来存放进程控制块
    size_t size;         //队列中有效进程的个数
    size_t capatity;     //队列的最大容量,如果数据达到最大容量,就要重新开辟一块更大的内存
}ProcQueue;
//进程队列初始化
void ProcQueueInit(ProcQueue* queue)
{
    if(queue == NULL)
    {
        return;
    }
    queue->size = 0;
    queue->capatity = 100;
    queue->data = (Proc*)malloc(sizeof(Proc)*queue->capatity);
    assert(queue->data != NULL);
}            
//销毁进程队列
void DestroyProcQueue(ProcQueue* queue)
{
    if(queue == NULL)
    {
        return;
    }                                                                                                                                   
    free(queue->data);
    queue->size = 0;
    queue->capatity = 0;
}
void ProcQueuePush(ProcQueue* queue,Proc pro);
//创建进程对象
void CreateProc(ProcQueue* queue, Proc* pro,size_t n)
{
    if(pro == NULL)
    {
        return;
    }
    strcpy(pro->next,pro->name); 
    size_t i = 0;
    printf("请输入进程编号(如P1,P2,P3)...\n");
    for(; i < n; ++i)
    {
        scanf("%s",pro->name);
        pro->status = R;
        srand((unsigned)time(NULL));//采用随机数法为每个进程输入对应数据
        pro->prio_num = rand()%6+1;
        pro->run_time = rand()%6+1;
        ProcQueuePush(queue,*pro);
    }
}
//如果当前进程队列满了,就要动态扩容
Proc* ProcQueueExpand(ProcQueue* queue)
{
    if(queue == NULL)
    {
        return NULL;
    }
    Proc* new_proc = (Proc*)malloc(sizeof(Proc)*2*queue->capatity+1);
    queue->capatity = 2*queue->capatity + 1;
    size_t i = 0;
    for(; i < queue->size ; i++)
    {
        new_proc[i] = queue->data[i];
    }
    free(queue->data);
    return new_proc;
}
//对进程队列进行冒泡排序
void ProcQueueBubble(ProcQueue* queue)
{
    if(queue == NULL)
    {
        return;
    }
    size_t i = 0;
    Proc tmp;
    for(;i < queue->size;i++)
    {
        size_t j = 0;
        for(; j < queue->size-i-1;j++)
        {
            if(queue->data[j].prio_num < queue->data[j+1].prio_num)                                                                     
            {
                tmp = queue->data[j];
                queue->data[j] = queue->data[j+1];
                queue->data[j+1] = tmp;
            }
        }
    }
}
//插入进程
void ProcQueuePush(ProcQueue* queue, Proc pro)
{
    if(queue == NULL)
    {
        return;
    }
    if(queue->size == queue->capatity)
    {
        //进程队列满了,进行动态扩容
        queue->data = ProcQueueExpand(queue);
    }
    //先插入到队列尾部,然后进行排序
    //每次的进程队列都是排好序的
    //如果新插入的进程状态为结束,就不进行排序
    if(pro.status != E)
    {
        queue->data[queue->size++] = pro;
        ProcQueueBubble(queue);
        size_t i = 0;
        for(; i < queue->size;i++)
        {
            if(i+1 == queue->size && queue->data[i+1].status != E)
            {
                strcpy(queue->data[i].next,queue->data[0].name);
            }
            else                                                                                                                        
            {
            strcpy(queue->data[i].next,queue->data[i+1].name);
            }
        }
    }
    else
    {
        strcpy(pro.next,"  ");
        queue->data[queue->size] = pro;
    }
}
//进程调度
void ProcQueueRun(ProcQueue* queue)
{
    if(queue == NULL )
    {
        return;
    }
    if(queue->size != 0)
    {
        if(queue->data[0].run_time > 0)//进程运行时间大于0才能进行调度
        {
            queue->data[0].run_time--;//运行时间减一
            queue->data[0].prio_num--;//优先级数减一
        }
        else
        {
            queue->data[0].status = E;//否则进程状态设置为E
        }
        Proc run_proc = queue->data[0];
        size_t i = 0;
        for(;i < queue->size-1;i++)
        {
            queue->data[i] = queue->data[i+1];
        }                                                                                                                               
        queue->size--;                //进程调度时相当于出队列,所以要从队列中删除
       ProcQueuePush(queue,run_proc); //调度完再入队列
    }
}
//打印进程队列信息
void ProcQueuePrint(ProcQueue* queue,size_t n)
{
    if(queue == NULL)
    {
        return;
    }
    printf("=============================\n");
    printf("NAME STATUS RUNTIME NICE NEXT\n");
    printf("=============================\n");
    size_t i = 0;
    for(; i < n ; i++)
    {
        printf(" %s  ",queue->data[i].name);
        if(queue->data[i].status == R)
        {
            printf("   R   ");
        }else
        {
            printf("   E   ");
        }
        printf("   %lu    ",queue->data[i].run_time);
        printf("  %d  ",queue->data[i].prio_num);
        printf("  %s",queue->data[i].next);
        printf("\n");
    }
}
int main()
{
    ProcQueue queue;
    Proc pro;                                                                                                                           
    size_t n = 0;
    ProcQueueInit(&queue);
    printf("请输入您想拥有的进程数: \n");
    scanf("%lu",&n);
    CreateProc(&queue,&pro,n);
    while(1)
    {
        if(queue.size == 0)
        {
            break;
        }
        printf("\n");
        ProcQueuePrint(&queue,n);
        getchar();
        ProcQueueRun(&queue);
    }
    ProcQueuePrint(&queue,n);
    return 0;
}   

开始状态以及调度一次后
这里写图片描述

运行一段时间后,始终按优先数大小排列
这里写图片描述

调度结束后,所有进程状态都为E
这里写图片描述

  • 20
    点赞
  • 167
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值