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

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

内容

(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:
操作系统---进程调度算法实现_第1张图片

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

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

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

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

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

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

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

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

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

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

算法流程图

操作系统---进程调度算法实现_第3张图片

代码及演示结果

#include                                                                                                      
#include 
#include 
#include 
#include 
#include 
#include 
#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;
}   

开始状态以及调度一次后
操作系统---进程调度算法实现_第4张图片

运行一段时间后,始终按优先数大小排列
操作系统---进程调度算法实现_第5张图片

调度结束后,所有进程状态都为E
操作系统---进程调度算法实现_第6张图片

你可能感兴趣的:(操作系统)