Operating system process scheduling experiment report

1. Purpose of the experiment

        Write and debug a process scheduler in a high-level language to deepen the understanding of process concepts and process scheduling algorithms

2. Experiment category

        Comprehensive experiment. Comprehensive knowledge of high-level language programming, process scheduling model, process scheduling algorithm and data structure

3. Experiment example

Example: Design a process scheduler with N processes running in parallel

Process Scheduling Algorithm: The scheduling algorithm with the highest priority number is adopted (that is, the processor is allocated to the process with the highest priority number) and the first-come, first-served algorithm.

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 artificially specified in advance (it can also be generated by random numbers). The arrival time of the process is the process input

entry time.

  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, the process will be canceled. If the occupied CPU time of the process has not reached the required running time after running a time slice, that is, the process It still needs to continue running. 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 required processes are completed.

The flow chart of the scheduling algorithm is as follows:

4. Source code

#include "stdio.h" 
#include <stdlib.h> 
#include <conio.h> 
#define getpch(type) (type*)malloc(sizeof(type)) //分配type类型大小的空间
#define NULL 0 
struct pcb { /* 定义进程控制块PCB */ 
char name[10]; //进程名
char state; //进程状态
int super; //进程优先级
int ntime; //进程总共需要运行的时间
int rtime; //进程已经运行的时间
struct pcb* link; //指向后继节点的指针
}*ready=NULL,*p;  //ready指针永远指向队列的第一个进程
typedef struct pcb PCB; 
  
sort() /* 建立对进程进行优先级排列函数*/ 
{ 
PCB *first, *second; // 指针second指向队列中当前处理的进程,指针first指向second的前驱节点,指针p指向准备插入队列的进程;
int insert=0; //判断是否
if((ready==NULL)||((p->super)>(ready->super))) /*优先级最大者,插入队首*/ 
{ 
p->link=ready; //p指向的进程优先级最高,要成为队列中新的队首节点,即ready要修改指向p;
ready=p; 
} 
else /* 如果队列有至少一个进程,则进程比较优先级,插入适当的位置中*/ 
{ 
first=ready; // first指向队首节点;
second=first->link; // second指向第2个节点;
while(second!=NULL) //如果有第2个节点,即队列至少有2个节点;
{ 
if((p->super)>(second->super)) /*若插入进程比当前进程优先数大,*/ 
{ /*插入到当前进程前面*/ //p指向的进程要插入到first和sencond之间,修改指针;
p->link=second; 
first->link=p; 
second=NULL; //找到了进程插入的位置,把second设为NULL,退出while循环;
insert=1; //insert为1表示p指向的进程插入在两个进程之间;
} 
else /* 插入进程优先数最低,则插入到队尾*/ 
{ 
first=first->link; // 此时first指向原队列最后一个进程;
second=second->link; //此时second为NULL;
} 
} 
if(insert==0) first->link=p; // insert为0表示p指向的进程插入到队尾
} 
}

input() /* 建立进程控制块函数*/ 
{ 
int i,num; 
//clrscr(); /*清屏*/ 
printf("\n 请输入进程号?"); //输入需要调度的进程数量
scanf("%d",&num); 
for(i=0;i<num;i++) //依次输入每个进程控制块的信息;
{ 
printf("\n 进程号No.%d:\n",i); 
p=getpch(PCB); 
printf("\n 输入进程名:"); 
scanf("%s",p->name); 
printf("\n 输入进程优先数:"); 
scanf("%d",&p->super); 
printf("\n 输入进程运行时间:"); 
scanf("%d",&p->ntime); 
printf("\n"); 
p->rtime=0;p->state='w'; 
p->link=NULL; 
sort(); /* 调用sort函数*/ //把新创建的进程按优先级插入到队列中;
} 
} 
int space() //获取当前队列的长度,即需要调度的进程个数;
{ 
int l=0; PCB* pr=ready; //pr指向队列第一个进程,即对首进程
while(pr!=NULL) //依次遍历整个队列,计算长度
{ 
l++; //是字符l,不是数字1,代表队列长度;
pr=pr->link;
} 
return(l); 
} 
disp(PCB * pr) /*建立进程显示函数,用于显示当前进程的信息*/ 
{ 
printf("\n qname \t state \t super \t ndtime \t runtime \n"); 
printf("|%s\t",pr->name); 
printf("|%c\t",pr->state); 
printf("|%d\t",pr->super); 
printf("|%d\t",pr->ntime); 
printf("|%d\t",pr->rtime); 
printf("\n"); 
}
check() /* 建立进程查看函数 */ //查看当前队列中每个进程信息
{ 
PCB* pr; 
printf("\n **** 当前正在运行的进程是:%s",p->name); /*显示当前运行进程*/ 
disp(p); 
pr=ready; // pr指向队列对首进程
printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/ 
while(pr!=NULL) //循环遍历队列中每个进程
{ 
disp(pr); 
pr=pr->link; 
} 
} 
destroy() /*建立进程撤消函数(进程运行结束,撤消进程)*/ 
{ 
printf("\n 进程 [%s] 已完成.\n",p->name); 
free(p); 
} 
running() /* 建立进程就绪函数(进程运行时间到,置就绪状态*/ 
{ 
(p->rtime)++; //p指向当前运行进程,即从原队列中的对首进程,运行次数加1,rtime表示已运行的时间片;
if(p->rtime==p->ntime) //如果进程需要运行总时间ntime和已运行时间rtime相等,表示该进程已经运行完毕,需要撤销;
destroy(); /* 调用destroy函数*/ 
else //如果该进程没有运行完毕,则使它的优先级减1,状态变为就绪,重新按优先级顺序插入到队列中;
{ 
(p->super)--; 
p->state='w'; 
sort(); /*调用sort函数*/ 
} 
} 
main() /*主函数*/ 
{ 
int len,h=0; //len:队列进程的个数;h:进程调度的时间片次数
char ch; // 获取getchar()函数的字符
input(); //输入要处理进程控制块信息
len=space(); //当前进程队列的长度,即要处理的进程数量
while((len!=0)&&(ready!=NULL)) //若队列不为空,即还有进程需要处理;
{ 
ch=getchar(); //从键盘获取字符
h++; // h:进程执行的时间片次数序号
printf("\n The execute number:%d \n",h); //
p=ready;  // ready永远指向队列的对首进程,p此时也指向队列的对首进程,但该对首进程需要出队列以便运行,;
ready=p->link; //原队列的第2个进程成为新的对首进程
p->link=NULL; //原对首进程出队列后,没有后继;
p->state='R'; //原对首进程出队列后状态变为执行;
check(); //查看当前队列中所有进程的信息,即原对首进程出队列后
running();//原对首进程运行
printf("\n 按任一键继续......"); 
ch=getchar();//从键盘获取字符
} 
printf("\n\n 进程已经完成.\n"); 
ch=getchar();//从键盘获取字符
}

5. Run the screenshot

 6. Summary of the report

        Through this experiment, the process of process dynamic scheduling is consistent with the results of manual analysis, and basically achieves the expected goal. Define the process number, process name, process priority number, and process running time through the user. The process with the highest priority enters the running state first, and the other processes are in the ready state. If a process with a high priority number still needs to run after one time slice, it will enter the ready state, and the process priority number -1. If the required running time has been reached after the process runs for a time slice, the process is completed and enters the completion state. If there are multiple processes with the same priority in the ready queue, they will be run on a first-come, first-served basis.

 

 

 

Guess you like

Origin blog.csdn.net/henry594xiaoli/article/details/129975734