计算机操纵系统实验:历程调度实验

打印 上一主题 下一主题

主题 626|帖子 626|积分 1878

目次


前言
二、实验目标
三、实验要求
四、实验原理
五、实验过程
六、代码详解
总结

前言

计算机操纵系统是管理计算机硬件和软件资源的核心软件,它负责为用户提供一个友爱、高效、安全的使用环境。历程调度是操纵系统的一个重要功能,它决定了历程在处理惩罚器上的执行顺序和时间,从而影响了系统的性能和用户的体验。本实验旨在通过模仿差别的历程调度算法,比力它们的优缺点,加深对操纵系统原理和设计的理解和把握。

一、开辟语言及实验平台
C++/JAVA
Turbo C / Microsoft Visual Studio 6.0 / Microsoft Visual Studio .NET 2010
在本文中使用的是c语言(?),使用的平台是devc++
二、实验目标

(1)加深对历程的概念及历程调度算法的理解;
(2)在了解和把握历程调度算法的基础上,体例历程调度算法通用步伐,将调试结果显示在计算机屏幕上,并检测机算和笔算的一致性。
三、实验要求

(1)了解历程调度;
(2)理解使用历程调度算法进行调度的原理;
(3)使用某种编程语言进行算法模仿。
四、实验原理



  • 例题:设计一个有N个历程的历程调度算法。
历程调度算法:采用最高优先数的调度算法(即把处理惩罚机分配给优先数最高的历程)。
每个历程有一个历程控制块(PCB)表示。历程控制块可以包含如下信息:历程名、优先数、到达时间、需要运行时间、已用CPU时间、历程状态等等。
历程的优先数及需要的运行时间可以事先人为的指定(也可以由随机数产生)。历程的到达时间为历程的输入的时间。历程的运行时间以时间片为单位进行计算。
每个历程的状态可以是停当W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。停当历程获得CPU后都只能运行一个时间片。用已占用CPU时间加1表示。
如果运行一个时间片后,历程的已占用CPU时间已达到所需要的运行时间,则撤销该历程,如果运行一个时间片后,历程的已占用CPU时间还未达到所需要的运行时间,也就是历程还需要继承运行,此时应该将历程的优先数减1(即降低一级),然后把它插入停当队列等待CPU。
每进行一次调度步伐都打印一次运行历程、停当队列、以及各个历程的PCB,以便进行检查。
重复以上过程,直到所要的历程都完成为止。
分析:
使用固定队列与静动态优先级结合,每个优先级为0~0xFF,而且以小的数字为高优先级,大的数字为低优先级,每次皆使用循环得到最高优先级的历程并执行,然后将其动态优先级设置为最低,并将其他历程动态优先级提高,以使得每个历程都有时机运行。历程的优先级与运行时间由随机数产生。

五、实验过程

代码如下:
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. /*常量和状态定义*/
  5. #define        PRO_NUM        0x05
  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 //255
  13. #define        MAX_PRIOR    0x00 0
  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. PCB_Info    g_queue[5];
  28. Uint32        g_time = 0;
  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<PRO_NUM;++i)
  68.    {
  69.        /*在这里修改随机数的范围,建议优先级取值为0到4之间,进程工作总时间为1到10之间*/
  70.        id=Create_Process(rand()%5, 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<PRO_NUM;++i)
  94.    {
  95.        g_queue[i].s_id=i;
  96.        g_queue[i].s_dynamic_prior=MIN_PRIOR; //255
  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. //g_queue[i].s_state=Sart;//这里有一个错误,在这里Sart并没有被定义,根据上下文,这里应该是想将进程的状态设置为START或者WAIT,根据上面的宏定义,将这里改成WAIT
  103.    }
  104. }
  105. Uint32 Create_Process(Uint32 pri,Uint32 needtime)
  106. {
  107.    int i=0;
  108.    Uint32 id=ID_ERROR;
  109.    for(i=0;i<PRO_NUM;++i)
  110.    {
  111.        if(g_queue[i].s_state ==FINISH)
  112.        {
  113.            id=g_queue[i].s_id;
  114.            g_queue[i].s_dynamic_prior=MIN_PRIOR;
  115.            g_queue[i].s_need_time=needtime;
  116.            g_queue[i].s_start_time=g_time;
  117.            g_queue[i].s_state=WAIT;
  118.            g_queue[i].s_static_prior=pri;
  119.            g_queue[i].s_used_time=0x0;
  120.            break;
  121.        }
  122.    }
  123.    return id;
  124. }
  125. void Run_Process()
  126. {
  127.    Uint32 id;   
  128.    while((id=Get_PriProcess())!=ID_ERROR)
  129.    {
  130.        Work_Process(id);
  131.        Change_Process(id);
  132.    }
  133. }
  134. void    Print_State()
  135. {
  136.    int i;
  137.    printf("时间 进程ID\t状态 已用时间 需要时间 开始时间 静优先级 动优先级\n");
  138.    for(i=0;i<PRO_NUM;++i)
  139.    {        
  140.        printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",g_time,g_queue[i].s_id,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,g_queue[i].s_dynamic_prior);
  142.    }
  143. }
  144. Uint32 Get_PriProcess()
  145. {
  146.    Uint32 id=ID_ERROR;
  147.    int  i, prev_id=ID_ERROR;
  148.    Uint32 prior=MIN_PRIOR*2, temp_prior;
  149.    for(i=0;i<PRO_NUM;++i)
  150.    {
  151.        if(g_queue[i].s_state!=FINISH)
  152.        {
  153.            temp_prior=g_queue[i].s_dynamic_prior+g_queue[i].s_static_prior;
  154.            if(temp_prior<=prior)
  155.            {
  156.                id=i;
  157.                prior=temp_prior;
  158.            }
  159.        }
  160.    }
  161.    return id;
  162. }
  163. void    Work_Process(Uint32 id)
  164. {
  165.    ++g_time;
  166.    g_queue[id].s_state=RUN;
  167.    ++g_queue[id].s_used_time;
  168.    Print_State();
  169. }
  170. void    Change_Process(Uint32 id)
  171. {
  172.    int i;
  173.    if(g_queue[id].s_need_time==g_queue[id].s_used_time)
  174.    {
  175.        g_queue[id].s_state=FINISH;
  176.    }
  177.    else
  178.    {
  179.        g_queue[id].s_dynamic_prior=MIN_PRIOR;
  180.        g_queue[id].s_state=WAIT;
  181.       
  182.    }
  183.    for(i=0;i<PRO_NUM;++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: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语言的历程调度步伐,现在来表明一下这段代码:
这段代码是一个简单的历程调度步伐,它使用优先级调度算法来模仿历程的执行。步伐中界说了一些常量和状态,包括历程数量、最大时间、等待状态、运行状态和完成状态。它还界说了一个PCB_Info布局体,用来表示历程的PCB(历程控制块),其中包含了历程的ID、静态优先级、动态优先级、开始时间、需要时间、已使用时间和状态。
代码中还界说了一个全局变量g_queue,用来表示历程队列,以及一个全局变量g_time,用来表示当前时间。此外,还界说了一些函数原型,包括模仿历程执行函数Simulator(),初始化5个历程函数Init_Process(),初始化历程队列函数Init_Queue(),创建历程函数Create_Process(),系统运行函数Run_Process(),得到最高优先级历程ID函数Get_PriProcess(),历程时间片执行函数Work_Process(),改变历程状态和优先级函数Change_Process(),打印历程状态函数Print_State()和竣事系统函数End_Process()。
在main()函数中调用了Simulator()函数来模仿整个系统的运行。Simulator()函数中依次调用了Init_Process()函数来初始化5个历程,Run_Process()函数来运行系统,并在末了调用End_Process()函数来竣事系统。
Init_Process()函数用来初始化5个历程。在这个函数中,起首调用了Init_Queue()函数来初始化历程队列,然后使用for循环来创建5个历程。在循环中,使用rand()函数来天生随机数,作为创建历程的优先级和需要时间的参数。然后调用Create_Process()函数来创建历程,并根据返回值判断是否创建成功。如果创建成功,则打印出历程的相干信息;否则,打印出创建失败的信息。
Init_Queue()函数用来初始化历程队列。在这个函数中,使用for循环来遍历历程队列中的每一个元素,并对其进行初始化。初始化包括设置历程的ID、动态优先级、需要时间、开始时间、静态优先级、已使用时间和状态。
Create_Process()函数用来创建历程。在这个函数中,起首遍历历程队列,寻找一个状态为FINISH的历程。如果找到了,则将其ID赋值给id变量,并对其进行初始化,包括设置动态优先级、需要时间、开始时间、状态、静态优先级和已使用时间。末了返回id变量的值。
Run_Process()函数用来运行系统。在这个函数中,起首调用Get_PriProcess()函数来获取最高优先级的历程ID。如果返回值不等于ID_ERROR,则调用Work_Process()函数来执行该历程,并调用Change_Process()函数来改变该历程的状态和优先级。然后继承循环,直到Get_PriProcess()函数返回ID_ERROR为止。
Get_PriProcess()函数用来获取最高优先级的历程ID。在这个函数中,起首界说了一个id变量并初始化为ID_ERROR,然后使用for循环来遍历历程队列中的每一个元素。对于每一个元素,如果它的状态不为FINISH,则计算它的优先级(静态优先级+动态优先级),并与当前最高优先级进行比力。如果它的优先级小于等于当前最高优先级,则更新id变量和当前最高优先级。末了返回id变量的值。
Work_Process()函数用来执行历程。在这个函数中,起首将全局变量g_time加1,然后将指定历程的状态设置为RUN,并将其已使用时间加1。末了调用Print_State()函数来打印历程状态。
Change_Process()函数用来改变历程状态和优先级。在这个函数中,起首判断指定历程是否已经完成(即已使用时间等于需要时间)。如果已经完成,则将其状态设置为FINISH;否则,将其动态优先级设置为MIN_PRIOR,并将其状态设置为WAIT。然后使用for循环来遍历历程队列中的其他元素,并对它们的动态优先级进行更新。
End_Process()函数用来竣事系统。在这个函数中,起首打印出所有历程竣事状态的信息,然后调用Print_State()函数来打印历程状态。末了打印出所有历程已经竣事的信息。
效果如下:



 以上。

总结

本实验通过编写一个C语言的历程调度步伐,来模仿优先级调度算法的过程和效果。步伐中界说了历程的PCB布局体,包含了历程的ID、静态优先级、动态优先级、开始时间、需要时间、已使用时间和状态等信息。步伐还界说了一些函数,用来初始化历程队列、创建历程、运行系统、获取最高优先级历程、执行历程、改变历程状态和优先级、打印历程状态和竣事系统等功能。步伐使用了随机数来天生历程的优先级和需要时间,并使用循环来遍历历程队列,找到最高优先级的历程并执行,然后降低其动态优先级,并提高其他历程的动态优先级,以保证每个历程都有时机运行。步伐在每次执行一个历程后,都会打印出当前的时间和所有历程的状态,以便观察和检查。步伐在所有历程都完成后,会打印出最终的结果,并竣事系统。
通过本实验,加深了对历程调度算法的理解和把握,熟悉了C语言的编程技巧和调试方法,提高了分析问题息争决问题的本领。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

灌篮少年

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表