• 操作系统进程调度算法的模拟实现(c语言版本)


            前言:本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解,完整代码放在文章末尾,欢迎大家自行拷贝调用

    目录

    常见的调度算法

    数据结构

    先来先服务调度算法

    算法模拟思路:

    算法模拟: 

    最短作业优先调度算法

    算法模拟思路:

    算法模拟:

     最高优先级调度算法

    算法模拟思路:

    算法模拟:

     时间片轮转调度算法

    算法模拟思路:

    算法模拟: 

    完整代码:

     course.h: 

    course.cpp:

    test.cpp: 


    常见的调度算法

    • 先来先服务调度算法
    • 最短作业优先调度算法
    • 高响应比优先调度算法
    • 最高优先级调度算法
    • 时间片轮转调度算法
    • 多级反馈队列调度算法
    • ... ...

    数据结构

    1. typedef struct program
    2. {
    3. char name[20];
    4. int running_time;
    5. int enter_time;
    6. int priority;
    7. int done_time; //用于时间片轮转
    8. int copyRunning_time; //用于时间片轮转
    9. int start_time;
    10. program* next;
    11. } Program;
    12. typedef struct programQueue
    13. {
    14. program* firstProg;
    15. program* LastProg;
    16. int size;
    17. } programQueue;

    先来先服务调度算法

            顾名思义,先来后到,每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。但是当一个长作业先运行了,那么后面的短作业等待的时间就会很长,不利于短作业。FCFS 对长作业有利,适用于 CPU 繁忙型作业的系统,而不适用于 I/O 繁忙型作业的系统。

    算法模拟思路:

    1. 首先将输入的进程放入一个进程数组中,然后根据进程的到达时间进行排序,将最先到达的进程放入进程就绪队列中。
    2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,并将在此进程执行期间到达的进程依次加入进程就绪队列。
    3. 如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    算法模拟: 

    1. //FCFS先来先服务算法
    2. void FCFS(program pro[], int num)
    3. {
    4. printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    5. sortWithEnterTime(pro, num); //按照进入顺序排序
    6. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    7. Queueinit(queue);
    8. EnterQueue(queue, &pro[0]);
    9. int time = pro[0].enter_time;
    10. int pronum = 1; //记录当前的进程
    11. float sum_T_time = 0, sum_QT_time = 0;
    12. while (queue->size > 0)
    13. {
    14. program* curpro = poll(queue); //从进程队列中取出进程
    15. if (time < curpro->enter_time)
    16. time = curpro->enter_time;
    17. int done_time = time + curpro->running_time;
    18. int T_time = done_time - curpro->enter_time;
    19. sum_T_time += T_time;
    20. float QT_time = T_time / (curpro->running_time + 0.0);
    21. sum_QT_time += QT_time;
    22. for (int tt = time; tt <= done_time && pronum < num; tt++)
    23. {
    24. //模拟进程的执行过程
    25. if (tt >= pro[pronum].enter_time)
    26. {
    27. EnterQueue(queue, &pro[pronum]);
    28. pronum++;
    29. }
    30. }
    31. printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    32. time += curpro->running_time;
    33. if (queue->size == 0 && pronum < num)
    34. {
    35. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    36. EnterQueue(queue, &pro[pronum]);
    37. pronum++;
    38. }
    39. }
    40. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
    41. }

    最短作业优先调度算法

            最短作业优先调度算法会优先选择运行时间最短的进程来运行,这有助于提高系统的吞吐量。这显然对长作业不利,很容易造成一种极端现象。比如,一个长作业在就绪队列等待运行,而这个就绪队列有非常多的短作业,那么就会使得长作业不断的往后推,周转时间变长,致使长作业长期不会被运行。

    算法模拟思路:

    1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
    2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
    3. 将这些到达的进程进行排序,按照进程服务时间的大小。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
    4. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    算法模拟:

    1. //短作业优先算法
    2. void SJF(program pro[], int num)
    3. {
    4. printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    5. sortWithEnterTime(pro, num);
    6. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    7. Queueinit(queue);
    8. EnterQueue(queue, &pro[0]);
    9. int time = pro[0].enter_time;
    10. int pronum = 1; //记录当前的进程
    11. float sum_T_time = 0, sum_QT_time = 0;
    12. while (queue->size > 0)
    13. {
    14. program* curpro = poll(queue); //从进程队列中取出进程
    15. if (time < curpro->enter_time)
    16. time = curpro->enter_time;
    17. int done_time = time + curpro->running_time;
    18. int T_time = done_time - curpro->enter_time;
    19. float QT_time = T_time / (curpro->running_time + 0.0);
    20. sum_T_time += T_time;
    21. sum_QT_time += QT_time;
    22. int pre = pronum;
    23. for (int tt = time; tt <= done_time && pronum < num; tt++)
    24. {
    25. //模拟进程的执行过程
    26. if (tt >= pro[pronum].enter_time)
    27. {
    28. // 统计从此任务开始到结束之间有几个进程到达
    29. pronum++;
    30. }
    31. }
    32. sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
    33. for (int i = pre; i < pronum; i++)
    34. {
    35. //将进程链入队列
    36. EnterQueue(queue, &pro[i]);
    37. }
    38. pre = pronum;
    39. printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    40. time += curpro->running_time;
    41. if (queue->size == 0 && pronum < num)
    42. {
    43. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    44. EnterQueue(queue, &pro[pronum]);
    45. pronum++;
    46. }
    47. }
    48. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / num);
    49. }

     最高优先级调度算法

    进程的优先级可以分为,静态优先级或动态优先级:

    • 静态优先级创建进程时候,就已经确定了优先级了,然后整个运行时间优先级都不会变化;
    • 动态优先级根据进程的动态变化调整优先级,比如如果进程运行时间增加,则降低其优先级,如果进程等待时间(就绪队列的等待时间)增加,则升高其优先级,也就是随着时间的推移增加等待进程的优先级。

    该算法也有两种处理优先级高的方法,非抢占式和抢占式:

    • 非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。
    • 抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。

    但是依然有缺点,可能会导致低优先级的进程永远不会运行

    算法模拟思路:

    1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
    2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
    3. 将这些到达的进程进行排序,按照进程优先权排序(权值小的先入)。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
    4. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    算法模拟:

    1. //优先权高者优先(HPF)
    2. void HPF(program pro[], int num)
    3. {
    4. printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    5. sortWithEnterTime(pro, num);
    6. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    7. Queueinit(queue);
    8. EnterQueue(queue, &pro[0]);
    9. int time = pro[0].enter_time;
    10. int pronum = 1; //记录当前的进程
    11. float sum_T_time = 0, sum_QT_time = 0;
    12. while (queue->size > 0)
    13. {
    14. program* curpro = poll(queue); //从进程队列中取出进程
    15. if (time < curpro->enter_time)
    16. time = curpro->enter_time;
    17. int done_time = time + curpro->running_time;
    18. int T_time = done_time - curpro->enter_time;
    19. float QT_time = T_time / (curpro->running_time + 0.0);
    20. sum_T_time += T_time;
    21. sum_QT_time += QT_time;
    22. int pre = pronum;
    23. for (int tt = time; tt <= done_time && pronum < num; tt++)
    24. {
    25. //模拟进程的执行过程
    26. if (tt >= pro[pronum].enter_time)
    27. {
    28. // 统计从此任务开始到结束之间有几个进程到达
    29. pronum++;
    30. }
    31. }
    32. sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
    33. for (int i = pre; i < pronum; i++)
    34. {
    35. //将进程链入队列
    36. EnterQueue(queue, &pro[i]);
    37. }
    38. pre = pronum;
    39. printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    40. time += curpro->running_time;
    41. if (queue->size == 0 && pronum < num)
    42. {
    43. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    44. EnterQueue(queue, &pro[pronum]);
    45. pronum++;
    46. }
    47. }
    48. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
    49. }

     时间片轮转调度算法

            每个进程被分配一个时间段,称为时间片,即允许该进程在该时间段中运行。如果时间片用完,进程还在运行,那么将会把此进程从 CPU 释放出来,并把 CPU 分配另外一个进程;如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换;如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率;如果设得太长又可能引起对短作业进程的响应时间变长。

    算法模拟思路:

    1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
    2. 当队列不空时,从队头取出一个进程来执行。此时分两种情况:①如果当前进程的剩余服务时间不大于时间片大小,说明此次将会将这个进程执 行完毕,在此进程执行过程中到达的进程需要添加到进程就绪队列中,这时就可以输出 此进程执行完毕②如果当前进程的剩余服务时间大于时间片大小,还需将此进程执行过程中到达 的进程需要添加到进程就绪队列中,然后此进程的剩余服务时间减少时间片大小,此进 程重新进入进程就绪队列
    3. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列

    算法模拟: 

    1. //时间片轮转(RR)
    2. void RR(program pro[], int num)
    3. {
    4. printf("请输入时间片大小");
    5. int timeslice; scanf("%d", ×lice);
    6. printf("进程 到达时间 服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
    7. sortWithEnterTime(pro, num);
    8. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    9. Queueinit(queue);
    10. pro[0].start_time = pro[0].enter_time;
    11. EnterQueue(queue, &pro[0]);
    12. int time = 0;
    13. int pronum = 1;
    14. float sum_T_time = 0, sum_QT_time = 0;
    15. while (queue->size > 0)
    16. {
    17. program* curpro = poll(queue); // 从队列中取出头节点
    18. if (time < curpro->enter_time)
    19. time = curpro->enter_time;
    20. if (timeslice >= curpro->running_time)
    21. {
    22. // 如果剩余时间小于时间片 则此任务完成
    23. for (int tt = time; tt <= time + curpro->running_time && pronum < num; tt++)
    24. {
    25. // 模拟进程的执行过程
    26. if (tt >= pro[pronum].enter_time)
    27. {
    28. // 统计从此任务开始到结束之间有几个进程到达
    29. pro[pronum].start_time = tt;
    30. EnterQueue(queue, &pro[pronum]);
    31. pronum++;
    32. }
    33. }
    34. time += curpro->running_time;
    35. curpro->running_time = 0;
    36. curpro->done_time = time;
    37. int T_time = curpro->done_time - curpro->start_time;
    38. float QT_time = T_time / (curpro->copyRunning_time + 0.0);
    39. sum_T_time += T_time;
    40. sum_QT_time += QT_time;
    41. printf("%s\t%d\t%d\t %d\t %d\t %d\t %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
    42. curpro->start_time, curpro->done_time, T_time, QT_time);
    43. if (queue->size == 0 && pronum < num)
    44. {
    45. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    46. pro[pronum].start_time = pro[pronum].enter_time;
    47. EnterQueue(queue, &pro[pronum]);
    48. pronum++;
    49. }
    50. continue;
    51. }
    52. for (int tt = time; tt <= time + timeslice && pronum < num; tt++)
    53. {
    54. //模拟进程的执行过程
    55. if (tt >= pro[pronum].enter_time)
    56. {
    57. // 统计从此任务开始到结束之间有几个进程到达
    58. pro[pronum].start_time = tt;
    59. EnterQueue(queue, &pro[pronum]);
    60. pronum++;
    61. }
    62. }
    63. time += timeslice;
    64. curpro->running_time -= timeslice;
    65. EnterQueue(queue, curpro); //当前程序未完成 继续添加到队列中
    66. if (queue->size == 0 && pronum < num)
    67. {
    68. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    69. pro[pronum].start_time = pro[pronum].enter_time;
    70. EnterQueue(queue, &pro[pronum]);
    71. pronum++;
    72. }
    73. }
    74. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
    75. }

    完整代码:

    我们分三个文件进行操作,当然大家也可以把三个文件按顺序放在一个文件里面进行操作

    course.h:      结构体的包含以及函数的声明

    course.cpp:  函数的具体实现

    test.cpp:       主函数用于调用其余文件函数

     course.h: 

    1. #pragma once
    2. #define _CRT_SECURE_NO_WARNINGS 1
    3. #include
    4. #include
    5. #include
    6. #include
    7. typedef struct program
    8. {
    9. char name[20];
    10. int running_time;
    11. int enter_time;
    12. int priority;
    13. int done_time; //用于时间片轮转
    14. int copyRunning_time; //用于时间片轮转
    15. int start_time;
    16. program* next;
    17. } Program;
    18. typedef struct programQueue
    19. {
    20. program* firstProg;
    21. program* LastProg;
    22. int size;
    23. } programQueue;
    24. //初始化
    25. void Queueinit(programQueue* queue);
    26. //打印
    27. void print(program pro[], int num);
    28. //打印队列
    29. void printQueue(programQueue* queue);
    30. //加入进程队列
    31. void EnterQueue(programQueue* queue, program* pro);
    32. //查询
    33. program* poll(programQueue* queue);
    34. //输入
    35. void inputProgram(program pro[], int num);
    36. //根据时间排序
    37. void sortWithEnterTime(program pro[], int num);
    38. //FCFS先来先服务算法
    39. void FCFS(program pro[], int num);
    40. //根据长度排序
    41. void sortWithLongth(program pro[], int start, int end);
    42. //短作业优先算法
    43. void SJF(program pro[], int num);
    44. //根据优先级排列
    45. void sortWithPriority(program pro[], int start, int end);
    46. //优先权高者优先(HPF)
    47. void HPF(program pro[], int num);
    48. //时间片轮转(RR)
    49. void RR(program pro[], int num);
    50. //选择菜单
    51. void choiceMenu();

    course.cpp:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include "course.h"
    3. //初始化
    4. void Queueinit(programQueue* queue)
    5. {
    6. if (queue == NULL)
    7. {
    8. return;
    9. }
    10. queue->size = 0;
    11. queue->LastProg = (program*)malloc(sizeof(program));
    12. queue->firstProg = queue->LastProg;
    13. }
    14. //打印
    15. void print(program pro[], int num)
    16. {
    17. for (int i = 0; i < num; i++)
    18. {
    19. printf("%d ", pro[i].enter_time);
    20. }
    21. }
    22. //打印输出队列
    23. void printQueue(programQueue* queue)
    24. {
    25. program* p = queue->firstProg->next;
    26. while (p != NULL)
    27. {
    28. printf("%s ", p->name);
    29. p = p->next;
    30. }
    31. printf("\n");
    32. }
    33. //加入进程队列
    34. void EnterQueue(programQueue* queue, program* pro)
    35. {
    36. queue->LastProg->next = (program*)malloc(sizeof(program));
    37. queue->LastProg = queue->LastProg->next;
    38. queue->LastProg->enter_time = pro->enter_time;
    39. memcpy(queue->LastProg->name, pro->name, sizeof(pro->name));
    40. queue->LastProg->priority = pro->priority;
    41. queue->LastProg->running_time = pro->running_time;
    42. queue->LastProg->copyRunning_time = pro->copyRunning_time;
    43. queue->LastProg->start_time = pro->start_time;
    44. queue->size++;
    45. }
    46. //查询
    47. program* poll(programQueue* queue)
    48. {
    49. program* temp = queue->firstProg->next;
    50. if (temp == queue->LastProg)
    51. {
    52. queue->LastProg = queue->firstProg;
    53. queue->size--;
    54. return temp;
    55. }
    56. queue->firstProg->next = queue->firstProg->next->next;
    57. queue->size--;
    58. return temp;
    59. }
    60. //输入
    61. void inputProgram(program pro[], int num)
    62. {
    63. for (int i = 0; i < num; i++)
    64. {
    65. program prog;
    66. printf("请输入第%d个进程的名字,到达时间,服务时间,优先级\n", i + 1);
    67. scanf("%s", prog.name);
    68. scanf("%d", &prog.enter_time);
    69. scanf("%d", &prog.running_time);
    70. prog.copyRunning_time = prog.running_time;
    71. scanf("%d", &prog.priority);
    72. pro[i] = prog;
    73. }
    74. }
    75. //根据时间排序
    76. void sortWithEnterTime(program pro[], int num)
    77. {
    78. for (int i = 1; i < num; i++)
    79. {
    80. for (int j = 0; j < num - i; j++)
    81. {
    82. if (pro[j].enter_time > pro[j + 1].enter_time)
    83. {
    84. program temp = pro[j];
    85. pro[j] = pro[j + 1];
    86. pro[j + 1] = temp;
    87. }
    88. }
    89. }
    90. }
    91. //FCFS先来先服务算法
    92. void FCFS(program pro[], int num)
    93. {
    94. printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    95. sortWithEnterTime(pro, num); //按照进入顺序排序
    96. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    97. Queueinit(queue);
    98. EnterQueue(queue, &pro[0]);
    99. int time = pro[0].enter_time;
    100. int pronum = 1; //记录当前的进程
    101. float sum_T_time = 0, sum_QT_time = 0;
    102. while (queue->size > 0)
    103. {
    104. program* curpro = poll(queue); //从进程队列中取出进程
    105. if (time < curpro->enter_time)
    106. time = curpro->enter_time;
    107. int done_time = time + curpro->running_time;
    108. int T_time = done_time - curpro->enter_time;
    109. sum_T_time += T_time;
    110. float QT_time = T_time / (curpro->running_time + 0.0);
    111. sum_QT_time += QT_time;
    112. for (int tt = time; tt <= done_time && pronum < num; tt++)
    113. {
    114. //模拟进程的执行过程
    115. if (tt >= pro[pronum].enter_time)
    116. {
    117. EnterQueue(queue, &pro[pronum]);
    118. pronum++;
    119. }
    120. }
    121. printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    122. time += curpro->running_time;
    123. if (queue->size == 0 && pronum < num)
    124. {
    125. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    126. EnterQueue(queue, &pro[pronum]);
    127. pronum++;
    128. }
    129. }
    130. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
    131. }
    132. //根据长度排序
    133. void sortWithLongth(program pro[], int start, int end)
    134. {
    135. int len = end - start;
    136. if (len == 1) return;
    137. for (int i = 1; i < len; i++) {
    138. for (int j = start; j < end - i; j++)
    139. {
    140. if (pro[j].running_time > pro[j + 1].running_time)
    141. {
    142. program temp = pro[j];
    143. pro[j] = pro[j + 1];
    144. pro[j + 1] = temp;
    145. }
    146. }
    147. }
    148. }
    149. //短作业优先算法
    150. void SJF(program pro[], int num)
    151. {
    152. printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    153. sortWithEnterTime(pro, num);
    154. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    155. Queueinit(queue);
    156. EnterQueue(queue, &pro[0]);
    157. int time = pro[0].enter_time;
    158. int pronum = 1; //记录当前的进程
    159. float sum_T_time = 0, sum_QT_time = 0;
    160. while (queue->size > 0)
    161. {
    162. program* curpro = poll(queue); //从进程队列中取出进程
    163. if (time < curpro->enter_time)
    164. time = curpro->enter_time;
    165. int done_time = time + curpro->running_time;
    166. int T_time = done_time - curpro->enter_time;
    167. float QT_time = T_time / (curpro->running_time + 0.0);
    168. sum_T_time += T_time;
    169. sum_QT_time += QT_time;
    170. int pre = pronum;
    171. for (int tt = time; tt <= done_time && pronum < num; tt++)
    172. {
    173. //模拟进程的执行过程
    174. if (tt >= pro[pronum].enter_time)
    175. {
    176. // 统计从此任务开始到结束之间有几个进程到达
    177. pronum++;
    178. }
    179. }
    180. sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
    181. for (int i = pre; i < pronum; i++)
    182. {
    183. //将进程链入队列
    184. EnterQueue(queue, &pro[i]);
    185. }
    186. pre = pronum;
    187. printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    188. time += curpro->running_time;
    189. if (queue->size == 0 && pronum < num)
    190. {
    191. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    192. EnterQueue(queue, &pro[pronum]);
    193. pronum++;
    194. }
    195. }
    196. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / num);
    197. }
    198. //根据优先级排列
    199. void sortWithPriority(program pro[], int start, int end)
    200. {
    201. int len = end - start;
    202. if (len == 1) return;
    203. for (int i = 1; i < len; i++)
    204. {
    205. for (int j = start; j < end - i; j++)
    206. {
    207. if (pro[j].priority > pro[j + 1].priority)
    208. {
    209. program temp = pro[j];
    210. pro[j] = pro[j + 1];
    211. pro[j + 1] = temp;
    212. }
    213. }
    214. }
    215. }
    216. //优先权高者优先(HPF)
    217. void HPF(program pro[], int num)
    218. {
    219. printf("进程 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    220. sortWithEnterTime(pro, num);
    221. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    222. Queueinit(queue);
    223. EnterQueue(queue, &pro[0]);
    224. int time = pro[0].enter_time;
    225. int pronum = 1; //记录当前的进程
    226. float sum_T_time = 0, sum_QT_time = 0;
    227. while (queue->size > 0)
    228. {
    229. program* curpro = poll(queue); //从进程队列中取出进程
    230. if (time < curpro->enter_time)
    231. time = curpro->enter_time;
    232. int done_time = time + curpro->running_time;
    233. int T_time = done_time - curpro->enter_time;
    234. float QT_time = T_time / (curpro->running_time + 0.0);
    235. sum_T_time += T_time;
    236. sum_QT_time += QT_time;
    237. int pre = pronum;
    238. for (int tt = time; tt <= done_time && pronum < num; tt++)
    239. {
    240. //模拟进程的执行过程
    241. if (tt >= pro[pronum].enter_time)
    242. {
    243. // 统计从此任务开始到结束之间有几个进程到达
    244. pronum++;
    245. }
    246. }
    247. sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
    248. for (int i = pre; i < pronum; i++)
    249. {
    250. //将进程链入队列
    251. EnterQueue(queue, &pro[i]);
    252. }
    253. pre = pronum;
    254. printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    255. time += curpro->running_time;
    256. if (queue->size == 0 && pronum < num)
    257. {
    258. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    259. EnterQueue(queue, &pro[pronum]);
    260. pronum++;
    261. }
    262. }
    263. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
    264. }
    265. //时间片轮转(RR)
    266. void RR(program pro[], int num)
    267. {
    268. printf("请输入时间片大小");
    269. int timeslice; scanf("%d", ×lice);
    270. printf("进程 到达时间 服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
    271. sortWithEnterTime(pro, num);
    272. programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    273. Queueinit(queue);
    274. pro[0].start_time = pro[0].enter_time;
    275. EnterQueue(queue, &pro[0]);
    276. int time = 0;
    277. int pronum = 1;
    278. float sum_T_time = 0, sum_QT_time = 0;
    279. while (queue->size > 0)
    280. {
    281. program* curpro = poll(queue); // 从队列中取出头节点
    282. if (time < curpro->enter_time)
    283. time = curpro->enter_time;
    284. if (timeslice >= curpro->running_time)
    285. {
    286. // 如果剩余时间小于时间片 则此任务完成
    287. for (int tt = time; tt <= time + curpro->running_time && pronum < num; tt++)
    288. {
    289. // 模拟进程的执行过程
    290. if (tt >= pro[pronum].enter_time)
    291. {
    292. // 统计从此任务开始到结束之间有几个进程到达
    293. pro[pronum].start_time = tt;
    294. EnterQueue(queue, &pro[pronum]);
    295. pronum++;
    296. }
    297. }
    298. time += curpro->running_time;
    299. curpro->running_time = 0;
    300. curpro->done_time = time;
    301. int T_time = curpro->done_time - curpro->start_time;
    302. float QT_time = T_time / (curpro->copyRunning_time + 0.0);
    303. sum_T_time += T_time;
    304. sum_QT_time += QT_time;
    305. printf("%s\t%d\t%d\t %d\t %d\t %d\t %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
    306. curpro->start_time, curpro->done_time, T_time, QT_time);
    307. if (queue->size == 0 && pronum < num)
    308. {
    309. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    310. pro[pronum].start_time = pro[pronum].enter_time;
    311. EnterQueue(queue, &pro[pronum]);
    312. pronum++;
    313. }
    314. continue;
    315. }
    316. for (int tt = time; tt <= time + timeslice && pronum < num; tt++)
    317. {
    318. //模拟进程的执行过程
    319. if (tt >= pro[pronum].enter_time)
    320. {
    321. // 统计从此任务开始到结束之间有几个进程到达
    322. pro[pronum].start_time = tt;
    323. EnterQueue(queue, &pro[pronum]);
    324. pronum++;
    325. }
    326. }
    327. time += timeslice;
    328. curpro->running_time -= timeslice;
    329. EnterQueue(queue, curpro); //当前程序未完成 继续添加到队列中
    330. if (queue->size == 0 && pronum < num)
    331. {
    332. //防止出现前一个进程执行完到下一个进程到达之间无进程进入
    333. pro[pronum].start_time = pro[pronum].enter_time;
    334. EnterQueue(queue, &pro[pronum]);
    335. pronum++;
    336. }
    337. }
    338. printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
    339. }
    340. //选择菜单
    341. void choiceMenu()
    342. {
    343. printf("请选择进程调度算法:\n");
    344. printf("1.先来先服务算法\n");
    345. printf("2.短进程优先算法\n");
    346. printf("3.高优先级优先\n");
    347. printf("4.时间片轮转算法\n");
    348. }

    test.cpp: 

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"course.h"
    3. int main()
    4. {
    5. int proNum = 5; //5个进程
    6. program pro[5];
    7. inputProgram(pro, proNum);
    8. choiceMenu();
    9. int choice;
    10. do
    11. {
    12. scanf("%d", &choice);
    13. switch (choice)
    14. {
    15. case 1:
    16. system("cls");
    17. FCFS(pro, proNum);
    18. choiceMenu();
    19. break;
    20. case 2:
    21. system("cls");
    22. SJF(pro, proNum);
    23. choiceMenu();
    24. break;
    25. case 3:
    26. system("cls");
    27. HPF(pro, proNum);
    28. choiceMenu();
    29. break;
    30. case 4:
    31. system("cls");
    32. RR(pro, proNum);
    33. choiceMenu();
    34. break;
    35. default:
    36. printf("输入错误,请重新尝试\n");
    37. break;
    38. }
    39. } while (choice);
    40. return 0;
    41. }



    本次的分享就到此为止了,感谢您的支持,如果您有不同意见,欢迎评论区积极交流

  • 相关阅读:
    Hugging Face发布重量级版本:Transformer 4.42
    Me-and-My-Girlfriend-1
    Linux运维技能图谱
    EasyNLP玩转文本摘要(新闻标题)生成
    【马士兵】 Python基础--11
    超越所有人的成就,牛顿的光芒也无法掩盖的天才数学巨人
    【leetcode面试经典150题】71. 对称二叉树(C++)
    工作效率-十五分钟让你快速学习Markdown语法到精通排版实践备忘
    leetcode日记(32)字符串相乘
    YOLOv5的Tricks | 【Trick14】YOLOv5的val.py脚本的解析
  • 原文地址:https://blog.csdn.net/m0_69519887/article/details/134053438