[Operating system] Process scheduling algorithm based on dynamic priority - C language implementation (with code)

This article will introduce how to write a dynamic priority process scheduling algorithm and implement it in a slave language.

1. What is a dynamic priority scheduling algorithm

       After the process runs for a time slice, if the CPU time occupied by the process has reached the required running time, the process is canceled; if the CPU time occupied by the process has not reached the required running time after running for 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. Therefore, after each time slice in the program, it is necessary to adjust the priority of the program once, and find the process with the highest priority among all processes, and there are two ways to find the process with the highest priority among the processes: one One is to traverse all the processes to find all the processes; the second is to sort the processes according to the priority.

Second, the elements that must be included in the process pcb

     The process pcb must contain the following five elements, and other elements can be added as required:

pcb
process name
priority
time to run
elapsed time
state

3. Flowchart

4. Demonstration of examples

Four processes A, B, C, and D arrive at the same time, and the priority of each program is shown in the figure below:

process Time of arrival Starting time time to run priority Complete time
A 0 6 2 1 8
B 0 1 2 3 4
C 0 5 2 2 7
D 0 0 2 4 3

First time slice:

At this time, D has the highest priority and should be executed, so the start time of D is 0, the time slice ends, the priority is reduced by one, and the priority becomes 3

Second time slice:

At this time, B and D have the highest priority, both of which are 3. If they are executed in order, B will be executed, so the start of B is 1, the time slice ends, the priority is reduced by one, and the priority becomes 2

Third time slice:

At this time, D has the highest priority, the time slice ends, the priority is reduced by one, the priority becomes 2, and the operation ends

Fourth time slice:

At this time, B and C have the highest priority, both of which are 2, in order, B executes, the time slice ends, the priority decreases by one, the priority becomes 1, and the operation ends

Fifth time slice:

At this time, the priority of C is the highest, which is 2, and C is executed, so the start time of C is 5, the time slice ends, the priority is reduced by one, and the priority becomes 1

Sixth time slice:

The priorities of A and C are both 1, and A is executed, so the start time of A is 6, when the time slice ends, the priority is reduced by one, and the priority becomes 0

Seventh time slice:

C has the highest priority, C is executed, the time slice ends, the priority is reduced by one, the priority becomes 0, and the operation ends

Eighth time slice:

A runs, and is allowed to end

5. Realization

5.1. Data structure

       The chain structure is adopted, that is, one process can point to the next process, which is convenient to increase the number of processes. At the same time, if the process with the highest priority is obtained by using the traversal method, it is also very convenient to implement under the chain structure.

5.2 How to get the process with the highest priority in the process queue

        According to what I said before, there are two ways to find the process with the highest priority. One is to traverse all the processes, and the other is to sort all the processes according to the process priority. The operation of the first method is simple and the complexity is O(n), and the operation of the second method is more complicated and the complexity is n*logn. The author's implementation is the first one used.

5.3, the code is as follows

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

//动态优先级
typedef struct pcb {
	int pid;
	char state;//E为完成,R为正在运行,W为在就绪队列
	int total_time;//需要的时间
	int level;//优先级
	int cputime;//已经执行的时间
	int mark;//标志位,用来表示正在执行的进程,1为在cpu,0为不在cpu
	struct pcb* next;
}*proc;


//初始化进程,返回进程队列的尾指针
proc init_pcb(struct pcb* head,struct pcb* tail,int mark,int* proc_num) {
	int i;
	//static int pcb_id[20] = { 0 };
	//static int pcb_id_index = 0;
	int numofpcb;
	proc p, tmp;
	printf("please input the number of process:\n");
	scanf("%d", &numofpcb);
	printf("there are %d processes,please input pcb info:\n", numofpcb);
	p = (proc)malloc(sizeof(struct pcb));
	printf("process id:");
	scanf("%d", &p->pid);
	//do {
	  //printf("process id:");
	  //scanf("%d", &p->pid);
	//	if (pcb_id_index != 0) {
	//		for (int i = 0; i < pcb_id_index; i++) {
	//			if (p->pid == pcb_id[i]) {
	//				printf("process id exist!\n");
	//				break;
	//			}
	//		}
	//	}
	//} while (1);
	//pcb_id[pcb_id_index] = p->pid;
	//pcb_id_index++;
	printf("the processes level:");
	scanf("%d", &p->level);
	printf("cputime required:");
	scanf("%d", &p->total_time);
	p->state = 'W';
	p->cputime = 0;
	p->mark = mark;
	head = p;

	for (i = numofpcb; i > 1; i--) {
		tmp = p;
		p = (proc)malloc(sizeof(struct pcb));
		printf("process id:");
		scanf("%d", &p->pid);
		printf("the processes level:");
		scanf("%d", &p->level);
		printf("cputime required:");
		scanf("%d", &p->total_time);
		p->state = 'W';
		p->cputime = 0;
		p->mark = 0;
		tmp->next = p;
	}
	tail = p;
	p->next = head;
	*proc_num = (*proc_num) + numofpcb;
	return tail;
}


//找到进程队列中优先级最高的进程,并将该进程指针返回
proc find_max_level(proc node, struct pcb* head,int* proc_num) {
	int maxlevel;
	proc p = head;
	proc tmp = p, res = p;
	tmp = node;
	//从头指针开始找优先级最大的进程
	maxlevel = head->level;
	proc find = head;
	for (int i = 0; i < *proc_num; i++) {
		//if (find->state == 'E') {
		//	find = find->next;
		//	continue;
		//}
		if (find->level >= maxlevel) {
			res = find;
			tmp->mark = 0;
			res->mark = 1;
			tmp = res;
			maxlevel = res->level;
		}
		find = find->next;
	}
	return res;
}



//调整所有进程的优先级,正在执行的优先级减一
void set_all_process_level(proc nowrunning,int* proc_num) {
	proc temp = nowrunning;
	nowrunning->level--;
}

//打印进程的id、cpu_time、req_time、level
void display(struct pcb* head,int* proc_num) {
	int i;
	proc p = head;
	printf("pid cpu_time req_time level\n");
	for (i = 0; i < *proc_num; i++) {
		printf("%d\t%d\t%d\t%d\n", p->pid, p->cputime, p->total_time, p->level);
		p = p->next;
	}
	printf("----------------------------------\n");
}

//删除进程队列中已经完成的进程
proc delete_finished_pro(proc node, struct pcb* head, struct pcb* tail,int* proc_num) {
	proc pre = tail;
	//通过id来识别已经完成的队列
	for (int i = 0; i < *proc_num; i++) {
		if (pre->next->pid == node->pid) {
			pre->next = node->next;
			tail = pre;
			head = pre->next;
			break;
		}
	}
	(*proc_num)--;
	return tail;
}

//插入新的进程,使用init_pcb()函数来完成,并将新进程插入到原进程队列中得到
//新的进程队列,并将新进程队列的尾指针返回
proc insert_proc(int* insertnum,proc head,proc tail,int* proc_num) {
	proc inhead = NULL, intail = NULL;
	intail = init_pcb(inhead, intail, 0,proc_num);
	inhead = intail->next;
	proc tmp = inhead;

	tail->next = inhead;
	tail = intail;
	tail->next = head;
	//*proc_num = (*proc_num) + *insertnum;
	return tail;
}

//用户选择是否插入新的进程,返回进程队列的尾指针
proc judg_insert_proc(int* insertnum,proc head,proc tail,int* proc_num) {
	int choice = 0;
	/*proc intail;*/
	printf("insert new processes or not,please input number(1 yes,0 no):");
	scanf("%d", &choice);
	if (choice == 1) {
		if (head == NULL) {//进程队列中没有进程了,直接使用init_pcb()函数
			tail = init_pcb(head, tail, 1, proc_num);
			head = tail->next;
			return tail;
		}
		tail = insert_proc(insertnum, head, tail,proc_num);
	}
	return tail;
}

//基于动态优先级的进程调度算法,找出优先级最大的进程执行,每一个cpu时间片,调整一次
//所有进程的优先级,再重新寻找优先级最高的进程
void priority(struct pcb* head, struct pcb* tail,int* proc_num) {
	int* insertnum = (int)malloc(sizeof(int));
	*insertnum = 0;
	int round = 1, i, maxlevel;
	proc p = head;
	proc t = tail;
	proc ntodo, nowmark;
	nowmark = p;
	ntodo = p;//leve最大的,马上要做的
	maxlevel = p->level;
	for (i = 0; i < *proc_num; i++) {
		p = p->next;
		if (p->level > maxlevel) {
			ntodo = p;
			nowmark->mark = 0;
			ntodo->mark = 1;
			nowmark = ntodo;
			maxlevel = ntodo->level;
		}
	}
	while (ntodo->total_time > ntodo->cputime)
	{
		*insertnum = 0;
		printf("\n* Round %d, Process %d is running\n", round, ntodo->pid);
		round++;
		ntodo->cputime++;
		if (ntodo->total_time == ntodo->cputime) {
			ntodo->state = 'E';
			tail = delete_finished_pro(ntodo, head, tail, proc_num);
			head = tail->next;
			set_all_process_level(ntodo,proc_num);
			display(head,proc_num);
			printf("\n▲ process %d is finished\n", ntodo->pid);

			if (head == tail) {
				head = NULL, tail = NULL;
			}

			
			tail = judg_insert_proc(insertnum, head, tail,proc_num);
			if (tail == NULL) {
				printf("over!!!\n");
				return;
			}
			head = tail->next;
			display(head, proc_num);
			ntodo = find_max_level(ntodo,head, proc_num);
			continue;
		}
		set_all_process_level(ntodo, proc_num);//重新调整level
		
		display(head, proc_num);
		tail = judg_insert_proc(insertnum, head, tail, proc_num);
		tail->next = head;
		ntodo = find_max_level(ntodo,head, proc_num);
	}
}

int main() {
	int* proc_num = (int)malloc(sizeof(int));
	*proc_num = 0;
	int mark = 1, inmark = 0;
	struct pcb* head = NULL, * tail = NULL;
	tail = init_pcb(head, tail,mark,proc_num);
	head = tail->next;
	display(head,proc_num);
	priority(head,tail,proc_num);
	return 0;
}

Guess you like

Origin blog.csdn.net/peng_lv/article/details/127814077