操作系统进程调度算法(c语言模拟实现)

马肤
这是懒羊羊

        前言:本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解,完整代码放在文章末尾,欢迎大家自行拷贝调用

目录

常见的调度算法

数据结构

先来先服务调度算法

算法模拟思路:

算法模拟: 

最短作业优先调度算法

算法模拟思路:

算法模拟:

 最高优先级调度算法

算法模拟思路:

算法模拟:

 时间片轮转调度算法

算法模拟思路:

算法模拟: 

完整代码:

 course.h: 

course.cpp:

test.cpp: 


常见的调度算法

  • 先来先服务调度算法
  • 最短作业优先调度算法
  • 高响应比优先调度算法
  • 最高优先级调度算法
  • 时间片轮转调度算法
  • 多级反馈队列调度算法
  • ... ...

    数据结构

    typedef struct program
    {
    	char name[20];
    	int running_time;
    	int enter_time;
    	int priority;
    	int done_time;			//用于时间片轮转
    	int copyRunning_time;   //用于时间片轮转
    	int start_time;
    	program* next;
    } Program;
    typedef struct programQueue
    {
    	program* firstProg;
    	program* LastProg;
    	int size;
    } programQueue;

    先来先服务调度算法

            顾名思义,先来后到,每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。但是当一个长作业先运行了,那么后面的短作业等待的时间就会很长,不利于短作业。FCFS 对长作业有利,适用于 CPU 繁忙型作业的系统,而不适用于 I/O 繁忙型作业的系统。

    算法模拟思路:

    1. 首先将输入的进程放入一个进程数组中,然后根据进程的到达时间进行排序,将最先到达的进程放入进程就绪队列中。
    2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,并将在此进程执行期间到达的进程依次加入进程就绪队列。
    3. 如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    算法模拟: 

    //FCFS先来先服务算法
    void FCFS(program pro[], int num)
    {
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro, num);    //按照进入顺序排序 
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    	Queueinit(queue);
    	EnterQueue(queue, &pro[0]);
    	int time = pro[0].enter_time;
    	int pronum = 1;    //记录当前的进程 
    	float sum_T_time = 0, sum_QT_time = 0;
    	while (queue->size > 0)
    	{
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if (time enter_time)
    			time = curpro->enter_time;
    		int done_time = time + curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		sum_T_time += T_time;
    		float QT_time = T_time / (curpro->running_time + 0.0);
    		sum_QT_time += QT_time;
    		for (int tt = time; tt = pro[pronum].enter_time)
    			{
    				EnterQueue(queue, &pro[pronum]);
    				pronum++;
    			}
    		}
    		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    		time += curpro->running_time;
    		if (queue->size == 0 && pronum  
    

    最短作业优先调度算法

            最短作业优先调度算法会优先选择运行时间最短的进程来运行,这有助于提高系统的吞吐量。这显然对长作业不利,很容易造成一种极端现象。比如,一个长作业在就绪队列等待运行,而这个就绪队列有非常多的短作业,那么就会使得长作业不断的往后推,周转时间变长,致使长作业长期不会被运行。

    算法模拟思路:

    1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
    2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
    3. 将这些到达的进程进行排序,按照进程服务时间的大小。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
    4. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

    算法模拟:

    //短作业优先算法
    void SJF(program pro[], int num)
    {
    	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
    	sortWithEnterTime(pro, num);
    	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
    	Queueinit(queue);
    	EnterQueue(queue, &pro[0]);
    	int time = pro[0].enter_time;
    	int pronum = 1;    //记录当前的进程 
    	float sum_T_time = 0, sum_QT_time = 0;
    	while (queue->size > 0)
    	{
    		program* curpro = poll(queue);   //从进程队列中取出进程 
    		if (time enter_time)
    			time = curpro->enter_time;
    		int done_time = time + curpro->running_time;
    		int T_time = done_time - curpro->enter_time;
    		float QT_time = T_time / (curpro->running_time + 0.0);
    		sum_T_time += T_time;
    		sum_QT_time += QT_time;
    		int pre = pronum;
    		for (int tt = time; tt = pro[pronum].enter_time)
    			{
    				// 统计从此任务开始到结束之间有几个进程到达 
    				pronum++;
    			}
    		}
    		sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
    		for (int i = pre; i name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
    		time += curpro->running_time;
    		if (queue->size == 0 && pronum  
    

     最高优先级调度算法

    进程的优先级可以分为,静态优先级或动态优先级:

    • 静态优先级:创建进程时候,就已经确定了优先级了,然后整个运行时间优先级都不会变化;
    • 动态优先级:根据进程的动态变化调整优先级,比如如果进程运行时间增加,则降低其优先级,如果进程等待时间(就绪队列的等待时间)增加,则升高其优先级,也就是随着时间的推移增加等待进程的优先级。

      该算法也有两种处理优先级高的方法,非抢占式和抢占式:

      • 非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。
      • 抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。

        但是依然有缺点,可能会导致低优先级的进程永远不会运行

        算法模拟思路:

        1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
        2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
        3. 将这些到达的进程进行排序,按照进程优先权排序(权值小的先入)。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
        4. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

        算法模拟:

        //优先权高者优先(HPF)
        void HPF(program pro[], int num)
        {
        	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
        	sortWithEnterTime(pro, num);
        	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
        	Queueinit(queue);
        	EnterQueue(queue, &pro[0]);
        	int time = pro[0].enter_time;
        	int pronum = 1;    //记录当前的进程 
        	float sum_T_time = 0, sum_QT_time = 0;
        	while (queue->size > 0)
        	{
        		program* curpro = poll(queue);   //从进程队列中取出进程 
        		if (time enter_time)
        			time = curpro->enter_time;
        		int done_time = time + curpro->running_time;
        		int T_time = done_time - curpro->enter_time;
        		float QT_time = T_time / (curpro->running_time + 0.0);
        		sum_T_time += T_time;
        		sum_QT_time += QT_time;
        		int pre = pronum;
        		for (int tt = time; tt = pro[pronum].enter_time)
        			{
        				// 统计从此任务开始到结束之间有几个进程到达 
        				pronum++;
        			}
        		}
        		sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
        		for (int i = pre; i name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
        		time += curpro->running_time;
        		if (queue->size == 0 && pronum  
        

         时间片轮转调度算法

                每个进程被分配一个时间段,称为时间片,即允许该进程在该时间段中运行。如果时间片用完,进程还在运行,那么将会把此进程从 CPU 释放出来,并把 CPU 分配另外一个进程;如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换;如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率;如果设得太长又可能引起对短作业进程的响应时间变长。

        算法模拟思路:

        1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
        2. 当队列不空时,从队头取出一个进程来执行。此时分两种情况:①如果当前进程的剩余服务时间不大于时间片大小,说明此次将会将这个进程执 行完毕,在此进程执行过程中到达的进程需要添加到进程就绪队列中,这时就可以输出 此进程执行完毕②如果当前进程的剩余服务时间大于时间片大小,还需将此进程执行过程中到达 的进程需要添加到进程就绪队列中,然后此进程的剩余服务时间减少时间片大小,此进 程重新进入进程就绪队列
        3. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列

        算法模拟: 

        //时间片轮转(RR)
        void RR(program pro[], int num)
        {
        	printf("请输入时间片大小");
        	int timeslice; scanf("%d", &timeslice);
        	printf("进程 到达时间  服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
        	sortWithEnterTime(pro, num);
        	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
        	Queueinit(queue);
        	pro[0].start_time = pro[0].enter_time;
        	EnterQueue(queue, &pro[0]);
        	int time = 0;
        	int pronum = 1;
        	float sum_T_time = 0, sum_QT_time = 0;
        	while (queue->size > 0)
        	{
        		program* curpro = poll(queue);    // 从队列中取出头节点 
        		if (time enter_time)
        			time = curpro->enter_time;
        		if (timeslice >= curpro->running_time)
        		{
        			// 如果剩余时间小于时间片  则此任务完成
        			for (int tt = time; tt running_time && pronum = pro[pronum].enter_time)
        				{
        					// 统计从此任务开始到结束之间有几个进程到达 
        					pro[pronum].start_time = tt;
        					EnterQueue(queue, &pro[pronum]);
        					pronum++;
        				}
        			}
        			time += curpro->running_time;
        			curpro->running_time = 0;
        			curpro->done_time = time;
        			int T_time = curpro->done_time - curpro->start_time;
        			float QT_time = T_time / (curpro->copyRunning_time + 0.0);
        			sum_T_time += T_time;
        			sum_QT_time += QT_time;
        			printf("%s\t%d\t%d\t  %d\t   %d\t %d\t  %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
        				curpro->start_time, curpro->done_time, T_time, QT_time);
        			if (queue->size == 0 && pronum running_time -= timeslice;
        		EnterQueue(queue, curpro);    //当前程序未完成  继续添加到队列中 
        		if (queue->size == 0 && pronum  
        

        完整代码:

        我们分三个文件进行操作,当然大家也可以把三个文件按顺序放在一个文件里面进行操作

        course.h:      结构体的包含以及函数的声明

        course.cpp:  函数的具体实现

        test.cpp:       主函数用于调用其余文件函数

         course.h: 

        #pragma once
        #define _CRT_SECURE_NO_WARNINGS 1
        #include
        #include
        #include 
        #include
        typedef struct program
        {
        	char name[20];
        	int running_time;
        	int enter_time;
        	int priority;
        	int done_time;			//用于时间片轮转
        	int copyRunning_time;   //用于时间片轮转
        	int start_time;
        	program* next;
        } Program;
        typedef struct programQueue
        {
        	program* firstProg;
        	program* LastProg;
        	int size;
        } programQueue;
        //初始化
        void Queueinit(programQueue* queue);
        //打印
        void print(program pro[], int num);
        //打印队列
        void printQueue(programQueue* queue);
        //加入进程队列 
        void EnterQueue(programQueue* queue, program* pro);
        //查询
        program* poll(programQueue* queue);
        //输入
        void inputProgram(program pro[], int num);
        //根据时间排序
        void sortWithEnterTime(program pro[], int num);
        //FCFS先来先服务算法
        void FCFS(program pro[], int num);
        //根据长度排序
        void sortWithLongth(program pro[], int start, int end);
        //短作业优先算法
        void SJF(program pro[], int num);
        //根据优先级排列
        void sortWithPriority(program pro[], int start, int end);
        //优先权高者优先(HPF)
        void HPF(program pro[], int num);
        //时间片轮转(RR)
        void RR(program pro[], int num);
        //选择菜单
        void choiceMenu();
        

        course.cpp:

        #define _CRT_SECURE_NO_WARNINGS 1
        #include "course.h"
        //初始化
        void Queueinit(programQueue* queue)
        {
        	if (queue == NULL)
        	{
        		return;
        	}
        	queue->size = 0;
        	queue->LastProg = (program*)malloc(sizeof(program));
        	queue->firstProg = queue->LastProg;
        }
        //打印
        void print(program pro[], int num)
        {
        	for (int i = 0; i firstProg->next;
        	while (p != NULL)
        	{
        		printf("%s ", p->name);
        		p = p->next;
        	}
        	printf("\n");
        }
        //加入进程队列 
        void EnterQueue(programQueue* queue, program* pro)
        {
        	queue->LastProg->next = (program*)malloc(sizeof(program));
        	queue->LastProg = queue->LastProg->next;
        	queue->LastProg->enter_time = pro->enter_time;
        	memcpy(queue->LastProg->name, pro->name, sizeof(pro->name));
        	queue->LastProg->priority = pro->priority;
        	queue->LastProg->running_time = pro->running_time;
        	queue->LastProg->copyRunning_time = pro->copyRunning_time;
        	queue->LastProg->start_time = pro->start_time;
        	queue->size++;
        }
        //查询
        program* poll(programQueue* queue)
        {
        	program* temp = queue->firstProg->next;
        	if (temp == queue->LastProg)
        	{
        		queue->LastProg = queue->firstProg;
        		queue->size--;
        		return temp;
        	}
        	queue->firstProg->next = queue->firstProg->next->next;
        	queue->size--;
        	return temp;
        }
        //输入
        void inputProgram(program pro[], int num)
        {
        	for (int i = 0; i  pro[j + 1].enter_time)
        			{
        				program temp = pro[j];
        				pro[j] = pro[j + 1];
        				pro[j + 1] = temp;
        			}
        		}
        	}
        }
        //FCFS先来先服务算法
        void FCFS(program pro[], int num)
        {
        	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
        	sortWithEnterTime(pro, num);    //按照进入顺序排序 
        	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
        	Queueinit(queue);
        	EnterQueue(queue, &pro[0]);
        	int time = pro[0].enter_time;
        	int pronum = 1;    //记录当前的进程 
        	float sum_T_time = 0, sum_QT_time = 0;
        	while (queue->size > 0)
        	{
        		program* curpro = poll(queue);   //从进程队列中取出进程 
        		if (time enter_time)
        			time = curpro->enter_time;
        		int done_time = time + curpro->running_time;
        		int T_time = done_time - curpro->enter_time;
        		sum_T_time += T_time;
        		float QT_time = T_time / (curpro->running_time + 0.0);
        		sum_QT_time += QT_time;
        		for (int tt = time; tt = pro[pronum].enter_time)
        			{
        				EnterQueue(queue, &pro[pronum]);
        				pronum++;
        			}
        		}
        		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
        		time += curpro->running_time;
        		if (queue->size == 0 && pronum  pro[j + 1].running_time)
        			{
        				program temp = pro[j];
        				pro[j] = pro[j + 1];
        				pro[j + 1] = temp;
        			}
        		}
        	}
        }
        //短作业优先算法
        void SJF(program pro[], int num)
        {
        	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
        	sortWithEnterTime(pro, num);
        	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
        	Queueinit(queue);
        	EnterQueue(queue, &pro[0]);
        	int time = pro[0].enter_time;
        	int pronum = 1;    //记录当前的进程 
        	float sum_T_time = 0, sum_QT_time = 0;
        	while (queue->size > 0)
        	{
        		program* curpro = poll(queue);   //从进程队列中取出进程 
        		if (time enter_time)
        			time = curpro->enter_time;
        		int done_time = time + curpro->running_time;
        		int T_time = done_time - curpro->enter_time;
        		float QT_time = T_time / (curpro->running_time + 0.0);
        		sum_T_time += T_time;
        		sum_QT_time += QT_time;
        		int pre = pronum;
        		for (int tt = time; tt = pro[pronum].enter_time)
        			{
        				// 统计从此任务开始到结束之间有几个进程到达 
        				pronum++;
        			}
        		}
        		sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
        		for (int i = pre; i name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
        		time += curpro->running_time;
        		if (queue->size == 0 && pronum  pro[j + 1].priority)
        			{
        				program temp = pro[j];
        				pro[j] = pro[j + 1];
        				pro[j + 1] = temp;
        			}
        		}
        	}
        }
        //优先权高者优先(HPF)
        void HPF(program pro[], int num)
        {
        	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
        	sortWithEnterTime(pro, num);
        	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
        	Queueinit(queue);
        	EnterQueue(queue, &pro[0]);
        	int time = pro[0].enter_time;
        	int pronum = 1;    //记录当前的进程 
        	float sum_T_time = 0, sum_QT_time = 0;
        	while (queue->size > 0)
        	{
        		program* curpro = poll(queue);   //从进程队列中取出进程 
        		if (time enter_time)
        			time = curpro->enter_time;
        		int done_time = time + curpro->running_time;
        		int T_time = done_time - curpro->enter_time;
        		float QT_time = T_time / (curpro->running_time + 0.0);
        		sum_T_time += T_time;
        		sum_QT_time += QT_time;
        		int pre = pronum;
        		for (int tt = time; tt = pro[pronum].enter_time)
        			{
        				// 统计从此任务开始到结束之间有几个进程到达 
        				pronum++;
        			}
        		}
        		sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
        		for (int i = pre; i name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
        		time += curpro->running_time;
        		if (queue->size == 0 && pronum size > 0)
        	{
        		program* curpro = poll(queue);    // 从队列中取出头节点 
        		if (time enter_time)
        			time = curpro->enter_time;
        		if (timeslice >= curpro->running_time)
        		{
        			// 如果剩余时间小于时间片  则此任务完成
        			for (int tt = time; tt running_time && pronum = pro[pronum].enter_time)
        				{
        					// 统计从此任务开始到结束之间有几个进程到达 
        					pro[pronum].start_time = tt;
        					EnterQueue(queue, &pro[pronum]);
        					pronum++;
        				}
        			}
        			time += curpro->running_time;
        			curpro->running_time = 0;
        			curpro->done_time = time;
        			int T_time = curpro->done_time - curpro->start_time;
        			float QT_time = T_time / (curpro->copyRunning_time + 0.0);
        			sum_T_time += T_time;
        			sum_QT_time += QT_time;
        			printf("%s\t%d\t%d\t  %d\t   %d\t %d\t  %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
        				curpro->start_time, curpro->done_time, T_time, QT_time);
        			if (queue->size == 0 && pronum running_time -= timeslice;
        		EnterQueue(queue, curpro);    //当前程序未完成  继续添加到队列中 
        		if (queue->size == 0 && pronum  
        

        test.cpp: 

        #define _CRT_SECURE_NO_WARNINGS 1
        #include"course.h"
        int main()
        {
        	int proNum = 5;		//5个进程
        	program pro[5];
        	inputProgram(pro, proNum);
        	choiceMenu();
        	int choice;
        	do
        	{
        		scanf("%d", &choice);
        		switch (choice)
        		{
        		case 1:
        			system("cls");
        			FCFS(pro, proNum);
        			choiceMenu();
        			break;
        		case 2:
        			system("cls");
        			SJF(pro, proNum);
        			choiceMenu();
        			break;
        		case 3:
        			system("cls");
        			HPF(pro, proNum);
        			choiceMenu();
        			break;
        		case 4:
        			system("cls");
        			RR(pro, proNum);
        			choiceMenu();
        			break;
        		default:
        			printf("输入错误,请重新尝试\n");
        			break;
        		}
        	} while (choice);
        	return 0;
        }
        



        本次的分享就到此为止了,感谢您的支持,如果您有不同意见,欢迎评论区积极交流


文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:表情:
评论列表 (暂无评论,0人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码