【操作系统】基于动态优先级的进程调度算法-C语言实现(有代码)

本文章将会介绍如何编写动态优先级的进程调度算法,并使用从语言实现。

一、什么是动态优先级的调度算法

       进程运行一个时间片后,如果进程已占用 CPU时间已达到所需要的运行时间,则撤消该进程;如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。所以在在该程序中每一个时间片后都需要调整一次程序的优先级,并且在所有的进程中找到优先级最大的进程,而实现在进程中找到优先级最大的进程有两种方式:一种是遍历所有的进程找到所有的进程;第二种是根据优先级对进程进行排序。

二、进程pcb中必须包含的元素

     进程pcb必须包含以下五个元素,可以按需求增加其他元素:

pcb
进程名
优先级
需要运行的时间
已经运行的时间
状态

三、流程图

四、例题展示

四个进程A、B、C、D,在同一时刻到达,个程序的优先级如下图所示:

进程 到达时间 开始时间 需要运行的时间 优先级 完成时间
A 0 6 2 1 8
B 0 1 2 3 4
C 0 5 2 2 7
D 0 0 2 4 3

第一个时间片:

此时D的优先级最高,应该执行,所以D的开始时间为0,时间片结束,优先级减一,优先级变为3

第二个时间片:

此时B和D的优先级最高,都为3,如果按顺序来执行,就是B执行,所以B的开始为1,时间片结束,优先级减一,优先级变为2

第三个时间片:

此时D的优先级最高,时间片结束,优先级减一,优先级变为2,运行结束

第四个时间片:

此时B、C的优先级最高,都为2,按顺序来,B执行,时间片结束,优先级减一,优先级变为1,运行结束

第五个时间片:

此时C的优先级最高,为2,C执行,所以C的开始时间为5,时间片结束,优先级减一,优先级变为1

第六个时间片:

A、C优先级都为1,A执行,所以A的开始时间为6,时间片结束,优先级减一,优先级变为0

第七个时间片:

C的优先级最高,C执行,时间片结束,优先级减一,优先级变为0,运行结束

第八个时间片:

A运行,并允许结束

五、具体实现

5.1、数据结构

       采用链式结构,即一个进程可以指向下一个进程,这样方便增加进程的个数,同时如果是使用遍历法求最大优先级的进程,在链式结构下也是十分方便实现的。

5.2、如何得到进程队列中优先级最大的进程

        按照之前说的找到优先级最大的进程有两种方法,一是遍历所有的进程,二是根据进程优先级对所有的进程进行排序。第一种方法的操作简单且复杂度为O(n),第二种方法操作较为复杂且复杂度为n*logn。作者的实现是使用的第一种。

5.3、代码如下

#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;
}

猜你喜欢

转载自blog.csdn.net/peng_lv/article/details/127814077