[purpose]
Write and debug a process scheduler in high-level language to deepen the understanding of process concept and process scheduling algorithm
[experimental equipment and software]
Experimental running environment: C language programming environment
Preparations before boarding include:
1. Prepare the procedure in advance according to the requirements of the experimental instruction;
2. Prepare intermediate data to be input;
3. Estimate possible problems;
4. Expected possible operation results.
[experimental principle]
1, Basic concepts
1. The concept of process;
2. Process status and process control block;
3. Process scheduling algorithm;
2, Process scheduling
1. Status of the process
2. Process structure - PCB
Processes are composed of a series of operations (actions) through which they complete their tasks. Therefore, different processes have different internal operations. In the operating system, in addition to the program and private data, the most important thing to describe a process is to need a data structure associated with the dynamic process. The data structure is used to describe the external characteristics (name, status, etc.) of the process and the connection (communication relationship) with other processes. The data structure is called process control block (PCB).
The process control block PCB corresponds to the process one by one. The PCB records all the information required by the system, all the information required to describe the process and all the information required to control the operation of the process. Therefore, the system can manage the process through the PCB of the process.
[experimental content, method, process and analysis]
1. Experimental content
Design a process scheduler with N processes in common.
Process scheduling algorithm: the highest priority number first scheduling algorithm (i.e. assigning the processor to the process with the highest priority number) and first come first serve algorithm are adopted. 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, etc. The priority number of processes and the required running time can be manually specified in advance (or generated by random numbers). The arrival time of the process is the time entered by the process. The running time of a process is calculated in time slices. The state of each process can be one of three states: ready W (Wait), running R (Run), or completed F (Finish). After the ready process obtains the CPU, it can only Run one time slice. It is represented by CPU time used plus 1. If the occupied CPU time of a process has reached the required running time after running a time slice, the process will be cancelled. If the occupied CPU time of a process has not reached the required running time after running a time slice, that is, the process needs to continue running, at this time, the priority of the process should be reduced by 1 (i.e. one level), Then insert it into the ready queue and Wait for the CPU. Each time, the scheduler prints the PCB of the running process, the ready queue, and each process for inspection.
Repeat the above process until all the processes are completed.
The flow chart of scheduling algorithm is as follows:
2. Experimental method and process
Experimental code #include <iostream> #include <stdlib.h> #include <time.h> using namespace std; #define getpch(type) (type *)malloc(sizeof(type)) int t=0; struct pcb{ /* Define process control block PCB */ char name[10]; //Process name char state; //W/R/F int super; //Priority number int ntime; //Total running time int rtime; //Time consuming struct pcb *link; } *ready = NULL, *p; typedef struct pcb PCB; void sort(){ /* Establish a prioritization function for processes*/ p->link=NULL; if(ready==NULL) ready=p; else{ if(p->super>ready->super){ p->link=ready; ready=p; } else{ PCB *f=ready; while(1){ if(f->link==NULL){ f->link=p; return; } else if(p->super > f->link->super){ PCB *s=f->link; f->link=p; p->link=s; return; } f=f->link; } } } } void input(){ /* Establish process control block function*/ srand((unsigned)time(NULL)); int n; string c; cout<<"Enter 1 random priority+Running time (1)-5),Enter other characters to customize the parameters:"; cin>>c; cout<<"Please enter the number of processes:"; cin>>n; for(int i=0;i<n;i++){ p=getpch(PCB); if(c=="1"){ cout<<"Please enter the process name"<<i+1<<": "; cin>>p->name; p->ntime=rand()%4+1; p->super=rand()%9+1; } else{ cout<<"Please enter the process name, process priority number and running time respectively:"; cin>>p->name>>p->super>>p->ntime; } p->state='W'; p->rtime=0; sort(); } } void disp(PCB *pr){ /*Establish a process display function to display the current process*/ cout<<"Process name:"<<pr->name<<" "; cout<<"Process status:"<<pr->state<<" "; cout<<"Number of process priorities:"<<pr->super<<" "; cout<<"Total process running time:"<<pr->ntime<<" "; cout<<"The process has taken time:"<<pr->rtime<<endl; } void check(){ /* Build process view function */ cout<<"-------------------"<<" Running process "<<"------------------------------"<<endl; disp(p); cout<<"-------------------"<<" Processes in the ready queue "<<"------------------------------"<<endl; PCB *pr=ready; while(pr!=NULL){ disp(pr); pr=pr->link; } } void destroy(){ /*Establish a process Undo function (undo the process after the process runs)*/ cout<<"process"<<p->name<<"Run complete, time consuming"<<p->ntime<<"individual CPU Time slice"<<endl; free(p); p=NULL; } void running(){ /* Establish the process ready function (when the process running time is up, set the ready state)*/ p=ready; ready=ready->link; t++; cout<<endl<<"This is the second"<<t<<"individual CPU Time slice"<<endl; p->state='R'; check(); p->rtime++; if(p->ntime==p->rtime) destroy(); else{ p->super-=1; p->state='W'; sort(); } if(p==NULL && ready==NULL) cout<<"All completed, time-consuming"<<t<<"individual CPU Time slice"<<endl; } int main(){ /*Main function*/ input(); while(p!=NULL || ready!=NULL) running(); return 0; }
Explanation of experiment code:
Use the given source code framework (each function name and process structure) to complete. Through observation, we can know that we first need to read in the process data and string the process data into a linked list, that is, the ready queue (assuming that the initial read in processes are in the ready state). There are many methods of reading in and sorting. Here I use insert sorting in input() The read format and interactive prompt are defined in the function. The total process running time is directly given to the random number (1-5), and the process priority number can be customized or random (1-10), as follows:
The current timestamp given by the random number seed prevents the random number from running the same every time srand((unsigned)time(NULL))
Each read in will assign the address of the current node (process) to the global variable p, and then take ready as the header node of the ready queue. Then, each read in will execute sort() once, because the insertion sort is used here, and each time find a suitable position to insert into the queue according to the priority number. As shown below, the insertion sort() flow chart of the above code:
That is, insert while inputting. When the input() function is executed, a ready queue with ready as the head node and linked list as the storage structure is obtained.
Then, just follow the flow chart given in the title. It is not difficult. It can be seen from the flow chart that there is a cycle, that is, a cycle is equivalent to a CPU time slice. For the cycle, use while() directly, and the condition for ending the cycle is that the ready queue and the running process are empty, that is, while (P! = null | ready! = null). P is equivalent to the running process.
Every time you enter running(), move the head node of the ready queue to p, that is, the process with the largest number of priorities enters the running state, and move the process out of the queue. If the time slice arrives (entering running is directly equivalent to the past CPU time slice, that is, the time slice arrives), the queue state returns to 'W', the time consumption has increased by 1, and then re insert p into the ready queue. If the process runs completely (total time required = elapsed time), then call destroy() to release the PCB.
destroy() is responsible for releasing the PCB, that is, releasing the process that is about to exit the running state, that is, p, and setting the p pointer to null.
2. Analysis of experimental results
Screenshot of experimental results:
[experimental summary]
P - > link = NULL in sorting is very important, which is discovered after debugging when I encounter a bug. Instead of initializing the link here, initializing p - > link in input() will easily cause the link of the last node of the linked list not to be NULL when scheduling later, that is, it will become a circular linked list, resulting in an endless loop of the check() function.
Experiments can strengthen the memory and understanding of theoretical knowledge. You must start to read the code when doing experiments. The overall difficulty is small, but the understanding and memory of PCB have been strengthened.