• 进程调度模拟


    1、核心思想:采用最高优先数的调度算法(即把处理机分配给优先数最高的进程)。

    2、实现方案:

    (1)先定义每个进程有一个进程控制块(PCB)表示。进程控制块包含如下信息:

    • 进程名 id
    • 静态优先级 static_prior
    • 动态优先级 dynamic_prior
    • 到达时间 start_time
    • 需要运行时间 need_time
    • 已用 CPU 时间 used_time
    • 进程状态 state

    (2)其次设计每个进程状态为就绪 W(Wait)、运行 R(Run)、或完成 F(Finish)三种状态。

    (3)使用一个固定就绪队列与进程静、动态优先级相结合的方式实现进程调度。 进程优先级范围0~0xFF(即 0~255),以小的数字为高优先级,大的数字为低优先级。每次都使用循环得到最高优先级的进程并执行(静态优先级+动态优先级的值最小的进程),然后将其动态优先级重置为最低 0xFF,并将其他进程动态优先级减 1 以提高,如此保证每个进程都有机会运行。

    (4)进程的静态优先级及需要的运行时间由随机数产生。每个进程在创建时默认动 态优先级为 0xFF。

    (5)进程的运行时间以时间片为单位进行计算。就绪进程获得 CPU 后都只能运行 一个时间片。利用已占用 CPU 时间加 1 来表示。如果运行一个时间片后,进程的已占用 CPU 时间已达到所需要的运行时间,则撤销该进程。如果运行一个时间片后,进程的已占用 CPU 时间还未达到所需要的运行时间,

    此时将进程的动态优先级重置为最低 0xFF,然后将它插入就绪队列等待 CPU。

    (6)每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。重复以上过程,直到所有的进程都完成为止。

    3、进程调度示意图

    示例:

    代码(procSched.c):

    1. #include
    2. #include
    3. #include
    4. /*常量和状态定义*/
    5. #define PRO_NUM 0x03
    6. #define MAX_TIME 0xFF
    7. /*进程状态宏*/
    8. #define WAIT 0x01
    9. #define RUN 0x02
    10. #define FINISH 0x03
    11. #define ID_ERROR 0x10
    12. #define MIN_PRIOR 0xFF
    13. #define MAX_PRIOR 0x00
    14. typedef unsigned int Uint32;
    15. /*进程PCB*/
    16. struct PCB_Info
    17. {
    18. Uint32 s_id;
    19. Uint32 s_static_prior;
    20. Uint32 s_dynamic_prior;
    21. Uint32 s_start_time;
    22. Uint32 s_need_time;
    23. Uint32 s_used_time;
    24. Uint32 s_state;
    25. };
    26. /*进程队列*/
    27. struct PCB_Info g_queue[5];
    28. Uint32 g_time;
    29. /*模拟进程执行函数*/
    30. void Simulator();
    31. /*初始化5个进程函数*/
    32. void Init_Process();
    33. /*初始化进程队列函数*/
    34. void Init_Queue();
    35. /*创建进程函数*/
    36. Uint32 Create_Process(Uint32 pri, Uint32 needtime);
    37. /*系统运行函数*/
    38. void Run_Process();
    39. /*得到最高优先级进程 ID函数*/
    40. Uint32 Get_PriProcess();
    41. /*进程时间片执行函数*/
    42. void Work_Process(Uint32 id);
    43. /*改变进程状态和优先级函数*/
    44. void Change_Process(Uint32 id);
    45. /*打印进程状态函数*/
    46. void Print_State();
    47. /*结束系统函数*/
    48. void End_Process();
    49. /*入口函数*/
    50. int main(int argc, char *argv[])
    51. {
    52. Simulator();
    53. return 0;
    54. }
    55. void Simulator()
    56. {
    57. Init_Process();
    58. Run_Process();
    59. End_Process();
    60. }
    61. void Init_Process()
    62. {
    63. int i;
    64. Uint32 id;
    65. srand((unsigned)time(NULL));
    66. Init_Queue();
    67. for (i = 0; i
    68. {
    69. /*在这里修改随机数的范围,建议优先级取值为0到4之间,进程工作总时间为1到10之间*/
    70. id = Create_Process(rand() % 4, 1 + rand() % 10);
    71. if (id != ID_ERROR)
    72. {
    73. printf("**********************************\n");
    74. printf("创建进程成功\n");
    75. printf("进程ID号为:%d\n", id);
    76. printf("进程的静态优先权为:%d\n", g_queue[id].s_static_prior);
    77. printf("进程的动态优先权为:%d\n", g_queue[id].s_dynamic_prior);
    78. printf("进程的到达时间为:%d\n", g_queue[id].s_start_time);
    79. printf("进程需要时间为:%d\n", g_queue[id].s_need_time);
    80. printf("进程已用CPU时间为:%d\n", g_queue[id].s_used_time);
    81. printf("进程的状态为:%d\n", g_queue[id].s_state);
    82. printf("\n");
    83. }
    84. else
    85. {
    86. printf("创建进程失败\n");
    87. }
    88. }
    89. }
    90. void Init_Queue()
    91. {
    92. int i;
    93. for (i = 0; i
    94. {
    95. g_queue[i].s_id = i;
    96. g_queue[i].s_dynamic_prior = MIN_PRIOR;
    97. g_queue[i].s_need_time = 0;
    98. g_queue[i].s_start_time = 0;
    99. g_queue[i].s_static_prior = MIN_PRIOR;
    100. g_queue[i].s_used_time = 0;
    101. g_queue[i].s_state = FINISH;
    102. }
    103. }
    104. Uint32 Create_Process(Uint32 pri, Uint32 needtime)
    105. {
    106. int i = 0;
    107. Uint32 id = ID_ERROR;
    108. for (i = 0; i
    109. {
    110. if (g_queue[i].s_state == FINISH)
    111. {
    112. id = g_queue[i].s_id;
    113. g_queue[i].s_dynamic_prior = MIN_PRIOR;
    114. g_queue[i].s_need_time = needtime;
    115. g_queue[i].s_start_time = g_time;
    116. g_queue[i].s_state = WAIT;
    117. g_queue[i].s_static_prior = pri;
    118. g_queue[i].s_used_time = 0x0;
    119. break;
    120. }
    121. }
    122. return id;
    123. }
    124. void Run_Process()
    125. {
    126. Uint32 id;
    127. while ((id = Get_PriProcess()) != ID_ERROR)
    128. {
    129. Work_Process(id);
    130. Change_Process(id);
    131. }
    132. }
    133. void Print_State()
    134. {
    135. int i;
    136. printf("时间 进程ID\t状态 已用时间 需要时间 开始时间 静优先级 动优先级\n");
    137. for (i = 0; i
    138. {
    139. printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", g_time, g_queue[i].s_id,
    140. g_queue[i].s_state, g_queue[i].s_used_time, g_queue[i].s_need_time,
    141. g_queue[i].s_start_time, g_queue[i].s_static_prior,
    142. g_queue[i].s_dynamic_prior);
    143. }
    144. }
    145. Uint32 Get_PriProcess()
    146. {
    147. Uint32 id = ID_ERROR;
    148. int i, prev_id = ID_ERROR;
    149. Uint32 prior = MIN_PRIOR * 2, temp_prior;
    150. for (i = 0; i
    151. {
    152. if (g_queue[i].s_state != FINISH)
    153. {
    154. temp_prior = g_queue[i].s_dynamic_prior + g_queue[i].s_static_prior;
    155. if (temp_prior <= prior)
    156. {
    157. id = i;
    158. prior = temp_prior;
    159. }
    160. }
    161. }
    162. return id;
    163. }
    164. void Work_Process(Uint32 id)
    165. {
    166. ++g_time;
    167. g_queue[id].s_state = RUN;
    168. ++g_queue[id].s_used_time;
    169. Print_State();
    170. }
    171. void Change_Process(Uint32 id)
    172. {
    173. int i;
    174. if (g_queue[id].s_need_time == g_queue[id].s_used_time)
    175. {
    176. g_queue[id].s_state = FINISH;
    177. }
    178. else
    179. {
    180. g_queue[id].s_dynamic_prior = MIN_PRIOR;
    181. g_queue[id].s_state = WAIT;
    182. }
    183. for (i = 0; i
    184. {
    185. if ((i != id) && (g_queue[i].s_state != FINISH))
    186. {
    187. g_queue[i].s_dynamic_prior>0 ? --(g_queue[i].s_dynamic_prior) : 0;
    188. }
    189. }
    190. }
    191. void End_Process()
    192. {
    193. printf("所有进程结束状态:\n");
    194. Print_State();
    195. printf("所有进程已经结束!\n");
    196. }

    思考练习:设计编写一个进程调度模拟程序(用C语言实现),完成对以下N个进程进行调度,并为整个进程序列计算出平均周转时间和平均带权周转时间。根据程序执行的打印结果,通过检测和笔算的一致性,来进行校验。

    公式:

    1. 周转时间=完成时间-提交时刻
    2. 平均周转时间=周转总时间/作业总个数
    3. 带权周转时间=周转时间/运行时间
    4. 平均带权周转时间=带权周转总时间/作业总个数

    进程号

    到达时间

    要求执行时间

    0

    0

    1

    1

    1

    35

    2

    2

    10

    3

    3

    5

    4

    6

    9

    5

    7

    21

    6

    9

    35

    7

    11

    23

    8

    12

    42

    9

    13

    1

    10

    14

    7

    代码:

    1. #include
    2. #include
    3. #include
    4. /*常量和状态定义*/
    5. #define PRO_NUM 0x0b // 11个进程
    6. #define MAX_TIME 0xFF // 动态优先级
    7. /*进程状态宏*/
    8. #define WAIT 0x01
    9. #define RUN 0x02
    10. #define FINISH 0x03
    11. #define ID_ERROR 0x10
    12. #define MIN_PRIOR 0xFF
    13. #define MAX_PRIOR 0x00
    14. typedef unsigned int Uint32;
    15. /*进程PCB*/
    16. struct PCB_Info
    17. {
    18. Uint32 s_id;
    19. Uint32 s_static_prior;
    20. Uint32 s_dynamic_prior;
    21. Uint32 s_start_time; // 改成进程到达时间
    22. Uint32 s_need_time; // 需要时间
    23. Uint32 s_used_time; // 已使用cpu时间
    24. Uint32 s_state;
    25. };
    26. /*周转时间数组*/
    27. Uint32 around_time[11];
    28. /*带权周转时间数组*/
    29. float Qaround_time[11];
    30. /*进程运行完毕标记*/
    31. bool flag[11];
    32. /*进程队列*/
    33. struct PCB_Info g_queue[11];
    34. Uint32 g_time;
    35. /*模拟进程执行函数*/
    36. void Simulator();
    37. /*初始化11个进程函数*/
    38. void Init_Process();
    39. /*初始化进程队列函数*/
    40. void Init_Queue();
    41. /*创建进程函数*/
    42. Uint32 Create_Process(Uint32 pri, Uint32 needtime, Uint32 arr_time);
    43. /*系统运行函数*/
    44. void Run_Process();
    45. /*得到最高优先级进程 ID函数*/
    46. Uint32 Get_PriProcess();
    47. /*进程时间片执行函数*/
    48. void Work_Process(Uint32 id);
    49. /*改变进程状态和优先级函数*/
    50. void Change_Process(Uint32 id);
    51. /*打印进程状态函数*/
    52. void Print_State();
    53. /*计算平均周转时间*/
    54. void Avg_around_time();
    55. /*计算带权平均周转时间*/
    56. void Avg_Qaround_time();
    57. /*结束系统函数*/
    58. void End_Process();
    59. /*入口函数*/
    60. int main(int argc, char* argv[])
    61. {
    62. Simulator();
    63. return 0;
    64. }
    65. void Simulator()
    66. {
    67. Init_Process();
    68. Run_Process();
    69. End_Process();
    70. }
    71. void Init_Process()
    72. {
    73. int i;
    74. Uint32 id;
    75. srand((unsigned)time(NULL));
    76. Init_Queue();
    77. int time, arr_time; // 进程工作总时间自己设定,进程到达时间
    78. for (i = 0; i < PRO_NUM; ++i)
    79. {
    80. /*在这里修改随机数的范围,建议优先级取值为0到12之间,进程工作总时间自己设定,进程到达时间*/
    81. printf("进程序列号:%d", i);
    82. printf("\n");
    83. printf("输入本进程到达的时间:");
    84. scanf_s("%d", &arr_time);
    85. printf("输入本进程所需要的时间:");
    86. scanf_s("%d", &time);
    87. id = Create_Process(rand() % 12, time, arr_time);
    88. if (id != ID_ERROR)
    89. {
    90. printf("**********************************\n");
    91. printf("创建进程成功\n");
    92. printf("进程ID号为:%d\n", id);
    93. printf("进程的静态优先权为:%d\n", g_queue[id].s_static_prior);
    94. printf("进程的动态优先权为:%d\n", g_queue[id].s_dynamic_prior);
    95. printf("进程的到达时间为:%d\n", g_queue[id].s_start_time);
    96. printf("进程需要时间为:%d\n", g_queue[id].s_need_time);
    97. printf("进程已用CPU时间为:%d\n", g_queue[id].s_used_time);
    98. printf("进程的状态为:%d\n", g_queue[id].s_state);
    99. printf("\n");
    100. }
    101. else
    102. {
    103. printf("创建进程失败\n");
    104. }
    105. }
    106. }
    107. void Init_Queue()
    108. {
    109. int i;
    110. for (i = 0; i < PRO_NUM; ++i)
    111. {
    112. g_queue[i].s_id = i;
    113. g_queue[i].s_dynamic_prior = MIN_PRIOR;
    114. g_queue[i].s_need_time = 0;
    115. g_queue[i].s_start_time = 0;
    116. g_queue[i].s_static_prior = MIN_PRIOR;
    117. g_queue[i].s_used_time = 0;
    118. g_queue[i].s_state = FINISH;
    119. }
    120. }
    121. Uint32 Create_Process(Uint32 pri, Uint32 needtime, Uint32 arr_time)
    122. {
    123. int i = 0;
    124. Uint32 id = ID_ERROR;
    125. for (i = 0; i < PRO_NUM; ++i)
    126. {
    127. if (g_queue[i].s_state == FINISH)
    128. {
    129. id = g_queue[i].s_id;
    130. g_queue[i].s_dynamic_prior = MIN_PRIOR;
    131. g_queue[i].s_need_time = needtime;
    132. g_queue[i].s_start_time = arr_time;
    133. g_queue[i].s_state = WAIT;
    134. g_queue[i].s_static_prior = pri;
    135. g_queue[i].s_used_time = 0x0;
    136. break;
    137. }
    138. }
    139. return id;
    140. }
    141. void Run_Process()
    142. {
    143. Uint32 id;
    144. while ((id = Get_PriProcess()) != ID_ERROR)
    145. {
    146. Work_Process(id);
    147. Change_Process(id);
    148. }
    149. }
    150. void Print_State()
    151. {
    152. int i;
    153. printf("时间 进程ID\t状态 已用时间 需要时间 开始时间 静优先级 动优先级 周转时间 带权周转时间\n");
    154. for (i = 0; i < PRO_NUM; ++i)
    155. {
    156. // 当进程运行时间等于所需时间时,且进程已运行完毕标志存在
    157. // 防止进程运行完毕之后,周转时间仍然增加
    158. if (g_queue[i].s_used_time == g_queue[i].s_need_time && flag[i] == false) {
    159. around_time[i] = g_time - g_queue[i].s_start_time;
    160. Qaround_time[i] = around_time[i] / g_queue[i].s_need_time;
    161. flag[i] = true;
    162. }
    163. printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t %d\t %.2f\n", g_time, g_queue[i].s_id,
    164. g_queue[i].s_state, g_queue[i].s_used_time, g_queue[i].s_need_time,
    165. g_queue[i].s_start_time, g_queue[i].s_static_prior,
    166. g_queue[i].s_dynamic_prior,around_time[i],Qaround_time[i]);
    167. }
    168. }
    169. Uint32 Get_PriProcess()
    170. {
    171. Uint32 id = ID_ERROR;
    172. int i, prev_id = ID_ERROR;
    173. Uint32 prior = MIN_PRIOR * 2, temp_prior;
    174. for (i = 0; i < PRO_NUM; ++i)
    175. {
    176. // 防止有些进程还没到达就开始运行
    177. if (g_queue[i].s_state != FINISH && (g_time >= g_queue[i].s_start_time))
    178. {
    179. temp_prior = g_queue[i].s_dynamic_prior + g_queue[i].s_static_prior;
    180. if (temp_prior <= prior)
    181. {
    182. id = i;
    183. prior = temp_prior;
    184. }
    185. }
    186. }
    187. return id;
    188. }
    189. void Work_Process(Uint32 id)
    190. {
    191. ++g_time;
    192. g_queue[id].s_state = RUN;
    193. ++g_queue[id].s_used_time;
    194. Print_State();
    195. }
    196. void Change_Process(Uint32 id)
    197. {
    198. int i;
    199. if (g_queue[id].s_need_time == g_queue[id].s_used_time)
    200. {
    201. g_queue[id].s_state = FINISH;
    202. }
    203. else
    204. {
    205. g_queue[id].s_dynamic_prior = MIN_PRIOR;
    206. g_queue[id].s_state = WAIT;
    207. }
    208. for (i = 0; i < PRO_NUM; ++i)
    209. {
    210. if ((i != id) && (g_queue[i].s_state != FINISH))
    211. {
    212. g_queue[i].s_dynamic_prior > 0 ? --(g_queue[i].s_dynamic_prior) : 0;
    213. }
    214. }
    215. }
    216. void End_Process()
    217. {
    218. printf("所有进程结束状态:\n");
    219. Print_State();
    220. Avg_around_time();
    221. Avg_Qaround_time();
    222. printf("所有进程已经结束!\n");
    223. }
    224. void Avg_around_time() {
    225. float sum = 0;
    226. for (int i = 0; i < PRO_NUM; i++) {
    227. sum += around_time[i];
    228. }
    229. printf("平均周转时间是:%.2f", sum / PRO_NUM);
    230. printf("\n");
    231. }
    232. void Avg_Qaround_time() {
    233. float sum = 0;
    234. for (int i = 0; i < PRO_NUM; i++) {
    235. sum += Qaround_time[i];
    236. }
    237. printf("平均周转时间是:%.2f", sum / PRO_NUM);
    238. printf("\n");
    239. }

    运行截图:

    over!

  • 相关阅读:
    数据集搜集
    【面试普通人VS高手系列】线程池如何知道一个线程的任务已经执行完成
    git 本地分支基础操作
    基于电商平台的商品的关键词文本匹配任务 有代码有数据
    关于我们编写好的java程序是如何运行部署的
    GIT 提交规范
    单片非晶磁性测量系统典型磁参数的不确定度与重复性
    配置之别名优化,映射器优化 P7,P8
    【Mysql】表的增删查改
    [计算机毕业设计成品]精品社区心理健康服务平台小程序系统|前后分离VUE[包运行成功]
  • 原文地址:https://blog.csdn.net/princekin_even/article/details/127441257