目录

前言

二、实验目的

三、实验要求

四、实验原理

五、实验过程

六、代码详解

总结


前言

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


一、开发语言及实验平台

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,并且以小的数字为高优先级,大的数字为低优先级,每次皆使用循环得到最高优先级的进程并执行,然后将其动态优先级设置为最低,并将其他进程动态优先级提高,以使得每个进程都有机会运行。进程的优先级与运行时间由随机数产生。

五、实验过程

代码如下:

#include #include #include /*常量和状态定义*/#definePRO_NUM0x05#defineMAX_TIME0xFF /*状态宏*/#defineWAIT0x01#defineRUN0x02#defineFINISH0x03#defineID_ERROR0x10#defineMIN_PRIOR0xFF //255#defineMAX_PRIOR0x00 0typedef unsigned intUint32;/*进程PCB*/struct PCB_Info{ Uint32s_id; Uint32s_static_prior; Uint32s_dynamic_prior; Uint32s_start_time; Uint32s_need_time; Uint32s_used_time; Uint32s_state;};/*进程队列*/PCB_Infog_queue[5];Uint32g_time = 0;/*模拟进程执行函数*/void Simulator();/*初始化5个进程函数*/void Init_Process();/*初始化进程队列函数*/void Init_Queue();/*创建进程函数*/Uint32 Create_Process(Uint32 pri,Uint32 needtime);/*系统运行函数*/void Run_Process();/*得到最高优先级进程 ID函数*/Uint32 Get_PriProcess();/*进程时间片执行函数*/voidWork_Process(Uint32 id);/*改变进程状态和优先级函数*/voidChange_Process(Uint32 id);/*打印进程状态函数*/voidPrint_State();/*结束系统函数*/void End_Process();/*入口函数*/int main( int argc, char *argv[ ]){ Simulator(); return 0;}void Simulator(){ Init_Process(); Run_Process(); End_Process();}void Init_Process(){ int i; Uint32 id; srand( (unsigned)time( NULL ) ); Init_Queue(); for(i=0;i<PRO_NUM;++i) { /*在这里修改随机数的范围,建议优先级取值为0到4之间,进程工作总时间为1到10之间*/ id=Create_Process(rand()%5, 1+rand()%10); if(id!=ID_ERROR) { printf("**********************************\n"); printf("创建进程成功\n"); printf("进程ID号为:%d\n",id); printf("进程的静态优先权为:%d\n",g_queue[id].s_static_prior); printf("进程的动态优先权为:%d\n",g_queue[id].s_dynamic_prior); printf("进程的到达时间为:%d\n",g_queue[id].s_start_time); printf("进程需要时间为:%d\n",g_queue[id].s_need_time); printf("进程已用CPU时间为:%d\n",g_queue[id].s_used_time); printf("进程的状态为:%d\n",g_queue[id].s_state); printf("\n"); } else { printf("创建进程失败\n"); } }}void Init_Queue(){ int i; for(i=0;i<PRO_NUM;++i) { g_queue[i].s_id=i; g_queue[i].s_dynamic_prior=MIN_PRIOR; //255 g_queue[i].s_need_time=0; g_queue[i].s_start_time=0; g_queue[i].s_static_prior=MIN_PRIOR; g_queue[i].s_used_time=0; g_queue[i].s_state=FINISH;//g_queue[i].s_state=Sart;//这里有一个错误,在这里Sart并没有被定义,根据上下文,这里应该是想将进程的状态设置为START或者WAIT,根据上面的宏定义,将这里改成WAIT }}Uint32 Create_Process(Uint32 pri,Uint32 needtime){ int i=0; Uint32 id=ID_ERROR; for(i=0;i<PRO_NUM;++i) { if(g_queue[i].s_state ==FINISH) { id=g_queue[i].s_id; g_queue[i].s_dynamic_prior=MIN_PRIOR; g_queue[i].s_need_time=needtime; g_queue[i].s_start_time=g_time; g_queue[i].s_state=WAIT; g_queue[i].s_static_prior=pri; g_queue[i].s_used_time=0x0; break; } } return id;}void Run_Process(){ Uint32 id; while((id=Get_PriProcess())!=ID_ERROR) { Work_Process(id); Change_Process(id); }}voidPrint_State(){ int i; printf("时间 进程ID\t状态 已用时间 需要时间 开始时间 静优先级 动优先级\n"); for(i=0;i<PRO_NUM;++i) { 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, g_queue[i].s_start_time,g_queue[i].s_static_prior,g_queue[i].s_dynamic_prior); }}Uint32 Get_PriProcess(){ Uint32 id=ID_ERROR; inti, prev_id=ID_ERROR; Uint32 prior=MIN_PRIOR*2, temp_prior; for(i=0;i<PRO_NUM;++i) { if(g_queue[i].s_state!=FINISH) { temp_prior=g_queue[i].s_dynamic_prior+g_queue[i].s_static_prior; if(temp_prior<=prior) { id=i; prior=temp_prior; } } } return id;}voidWork_Process(Uint32 id){ ++g_time; g_queue[id].s_state=RUN; ++g_queue[id].s_used_time; Print_State();}voidChange_Process(Uint32 id){ int i; if(g_queue[id].s_need_time==g_queue[id].s_used_time) { g_queue[id].s_state=FINISH;} else { g_queue[id].s_dynamic_prior=MIN_PRIOR; g_queue[id].s_state=WAIT;} for(i=0;i0 " />

六、代码详解

这是一段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语言的编程技巧和调试方法,提高了分析问题和解决问题的能力。