Computer Operating System Experiment: Process Scheduling Experiment

Table of contents

foreword

2. The purpose of the experiment

3. Experimental requirements

4. Experimental principle

5. Experimental process

6. Detailed Code Explanation

Summarize


foreword

Computer operating system is the core software that manages computer hardware and software resources, and it is responsible for providing users with a friendly, efficient and safe environment for use. Process scheduling is an important function of the operating system, which determines the execution order and time of processes on the processor, thereby affecting system performance and user experience. This experiment aims to deepen the understanding and mastery of operating system principles and design by simulating different process scheduling algorithms and comparing their advantages and disadvantages.


1. Development language and experimental platform

C++/JAVA

Turbo C / Microsoft Visual Studio 6.0 / Microsoft Visual Studio .NET 2010

In this article, the c language (?) is used, and the platform used is devc++

2. The purpose of the experiment

(1) Deepen the understanding of the concept of process and process scheduling algorithm;

(2) On the basis of understanding and mastering the process scheduling algorithm, compile a general program of the process scheduling algorithm, display the debugging results on the computer screen, and check the consistency of computer calculation and written calculation.

3. Experimental requirements

(1) Understand process scheduling;

(2) Understand the principle of scheduling using process scheduling algorithms;

(3) Use some programming language for algorithm simulation.

4. Experimental principle

  • Example: Design a process scheduling algorithm with N processes.

Process scheduling algorithm: use the scheduling algorithm with the highest priority number (that is, assign the processor to the process with the highest priority number).

Each process is represented by a Process Control Block (PCB). The process control block can contain the following information: process name, priority number, arrival time, required running time, used CPU time, process status and so on.

The priority number of the process and the required running time can be manually specified in advance (it can also be generated by a random number). The arrival time of the process is the time of the input to the process. The running time of a process is calculated in units of time slices.

The state of each process can be one of three states: ready W (Wait), running R (Run), or complete F (Finish). After the ready process obtains the CPU, it can only run for one time slice. It is expressed by adding 1 to the occupied CPU time.

If after running a time slice, the occupied CPU time of the process has reached the required running time, then cancel the process; if after running a time slice, the occupied CPU time of the process has not reached the required running time, that is The process still needs to continue to run. At this time, the priority number of the process should be reduced by 1 (that is, lowered by one level), and then inserted into the ready queue to wait for the CPU.

Every time the scheduler is executed, the running process, the ready queue, and the PCB of each process are printed for inspection.

Repeat the above process until all the desired processes are completed.

Analysis :

Use a combination of fixed queues and static and dynamic priorities, each priority is 0~0xFF, and the small number is the high priority, and the large number is the low priority. Use the loop to get the highest priority process and execute it every time. , then set its dynamic priority to the lowest and raise the dynamic priority of other processes so that each process has a chance to run. The priority and running time of the process are generated by random numbers.

5. Experimental process

code show as below:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

/*常量和状态定义*/
#define        PRO_NUM        0x05
#define        MAX_TIME    0xFF
   /*状态宏*/
#define        WAIT        0x01
#define        RUN            0x02
#define        FINISH        0x03

#define        ID_ERROR    0x10

#define        MIN_PRIOR    0xFF //255
#define        MAX_PRIOR    0x00 0


typedef unsigned int    Uint32;

/*进程PCB*/
struct PCB_Info
{
   Uint32    s_id;
   Uint32    s_static_prior;
   Uint32    s_dynamic_prior;
   Uint32    s_start_time;
   Uint32    s_need_time;
   Uint32    s_used_time;
   Uint32    s_state;
};

/*进程队列*/
PCB_Info    g_queue[5];
Uint32        g_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();
/*进程时间片执行函数*/
void    Work_Process(Uint32 id);
/*改变进程状态和优先级函数*/
void    Change_Process(Uint32 id);
/*打印进程状态函数*/
void    Print_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);
   }
}

void    Print_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;
   int  i, 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;
}

void    Work_Process(Uint32 id)
{
   ++g_time;
   g_queue[id].s_state=RUN;
   ++g_queue[id].s_used_time;
   Print_State();
}

void    Change_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;i<PRO_NUM;++i)
   {
       if((i!=id)&&(g_queue[i].s_state!=FINISH))
       {
           g_queue[i].s_dynamic_prior >0 ?--g_queue[i].s_dynamic_prior:g_queue[i].s_dynamic_prior=0;
       }
   }
}


void End_Process()
{
   printf("所有进程结束状态:\n");
   Print_State();
   printf("所有进程已经结束!\n");
}

6. Detailed Code Explanation

This is a process scheduler in C language, now to explain this code:

This code is a simple process scheduler that uses a priority scheduling algorithm to simulate the execution of processes. Some constants and states are defined in the program, including the number of processes, maximum time, waiting state, running state, and completion state. It also defines a PCB_Info structure, which is used to represent the PCB (process control block) of the process, which contains the ID, static priority, dynamic priority, start time, required time, used time and status of the process.

The code also defines a global variable g_queue, which is used to represent the process queue, and a global variable g_time, which is used to represent the current time. In addition, some function prototypes are defined, including the simulation process execution function Simulator(), the initialization of five process functions Init_Process(), the initialization process queue function Init_Queue(), the creation process function Create_Process(), and the system operation function Run_Process(). The highest priority process ID function Get_PriProcess(), process time slice execution function Work_Process(), change process state and priority function Change_Process(), print process state function Print_State() and end system function End_Process().

The Simulator() function is called in the main() function to simulate the operation of the whole system. In the Simulator() function, the Init_Process() function is called in turn to initialize five processes, the Run_Process() function is used to run the system, and finally the End_Process() function is called to end the system.

The Init_Process() function is used to initialize 5 processes. In this function, the Init_Queue() function is first called to initialize the process queue, and then a for loop is used to create 5 processes. In the loop, use the rand() function to generate a random number as the priority and time parameters of the creation process. Then call the Create_Process() function to create a process, and judge whether the creation is successful according to the return value. If the creation is successful, print out the relevant information of the process; otherwise, print out the information about the creation failure.

The Init_Queue() function is used to initialize the process queue. In this function, use a for loop to traverse each element in the process queue and initialize it. Initialization includes setting the process's ID, dynamic priority, required time, start time, static priority, elapsed time, and status.

The Create_Process() function is used to create a process. In this function, first traverse the process queue to find a process whose status is FINISH. If found, assign its ID to the id variable and initialize it, including setting dynamic priority, required time, start time, status, static priority, and used time. Finally returns the value of the id variable.

The Run_Process() function is used to run the system. In this function, first call the Get_PriProcess() function to obtain the highest priority process ID. If the return value is not equal to ID_ERROR, call the Work_Process() function to execute the process, and call the Change_Process() function to change the status and priority of the process. Then continue to loop until the Get_PriProcess() function returns ID_ERROR.

The Get_PriProcess() function is used to obtain the highest priority process ID. In this function, an id variable is first defined and initialized to ID_ERROR, and then a for loop is used to traverse each element in the process queue. For each element, if its state is not FINISH, calculate its priority (static priority + dynamic priority), and compare it with the current highest priority. If its priority is less than or equal to the current highest priority, update the id variable and the current highest priority. Finally returns the value of the id variable.

The Work_Process() function is used to execute the process. In this function, first add 1 to the global variable g_time, then set the state of the specified process to RUN, and add 1 to its elapsed time. Finally, the Print_State() function is called to print the process status.

The Change_Process() function is used to change the process status and priority. In this function, first judge whether the specified process has been completed (that is, the used time is equal to the required time). If it's done, set its state to FINISH; otherwise, set its dynamic priority to MIN_PRIOR and its state to WAIT. Then use a for loop to traverse other elements in the process queue and update their dynamic priorities.

The End_Process() function is used to end the system. In this function, first print out the information of the end state of all processes, and then call the Print_State() function to print the process state. Finally, print out the information that all processes have ended.

The effect is as follows:

 that's all.


Summarize

This experiment simulates the process and effect of the priority scheduling algorithm by writing a process scheduler in C language. The PCB structure of the process is defined in the program, which contains information such as process ID, static priority, dynamic priority, start time, required time, used time, and status. The program also defines some functions, which are used to initialize the process queue, create a process, run the system, obtain the highest priority process, execute the process, change the process status and priority, print the process status and end the system and other functions. The program uses random numbers to generate the priority of the process and the required time, and uses a loop to traverse the process queue, find the highest priority process and execute it, then reduce its dynamic priority, and increase the dynamic priority of other processes to ensure Every process has a chance to run. Every time the program executes a process, it will print out the current time and the status of all processes for observation and inspection. After all processes are completed, the program will print out the final result and end the system.

Through this experiment, the understanding and mastery of the process scheduling algorithm has been deepened, the programming skills and debugging methods of C language have been familiarized, and the ability of analyzing and solving problems has been improved.

Guess you like

Origin blog.csdn.net/m0_72471315/article/details/129878067