“时间片轮转”调度算法(C语言)

这篇具有很好参考价值的文章主要介绍了“时间片轮转”调度算法(C语言)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、算法实现流程图:

“时间片轮转”调度算法(C语言)

二、实现思路:

#define q 1 //时间片
要求:
PCB必须按顺序输入,到达时间从小到大。
实现:
难点在于PCB就否到达就绪队列的处理。
设标识变量,处理就绪队列,队列内有有效PCB和无效PCB(还未到达)

刚到达的PCB与执行一次时间片之后的PCB排序问题:
课本解释:当该进程的时间片耗尽或运行完毕时,系统再次将CRU分配给队首进程(或新到达的紧迫进程)。由此可保证就绪队列中的所有进程在一个确定的时间段内,都能够获得一次CPU执行。
因此:正确答案应该是,新到达的进程放就绪队列(有效PCB)队首。
执行完队头(有效PCB就绪队列的对头元素)元素后,在插入就绪队列,插入到有效PCB就绪队列的尾部

时间计算:Time(CPU执行总时间)还需要考虑CPU空闲时间(就绪队列内有效数据为0个时,且还有PCB未到达,就是计算CPU空闲时间的时候)
结束条件:必须是就绪队列内没有PCB(可能存在就绪队列内含有未到达PCB)

三、测试

说明:本代码只是针对课本给出的例子进行编写,因此会有很多漏洞!!
“时间片轮转”调度算法(C语言)也可测试同时到达。

四、代码

(visual studio 2019)文章来源地址https://www.toymoban.com/news/detail-453785.html

#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h" 
#include <stdlib.h> 
#include <conio.h> 
#define getpch(type) (type*)malloc(sizeof(type)) //快速malloc
#define NULL 0 
#define q 1 //时间片
/*
待实现:
PCB必须按顺序输入,到达时间从小到大。
	思路:
	1、新建标志变量,是否到达状态 
	2、处理就绪队列,队列内有有效PCB和无效PCB(还未到达)
	3、处理完队头(有效PCB就绪队列的对头元素)元素后,在插入就绪队列,插入到有效PCB就绪队列的尾部
	4、结束条件:必须是就绪队列内没有PCB
	5、时间计算:除了-到达时间外,还需要考虑CPU空闲时间(就绪队列内有效数据为null时,就是计算空闲时间的时候)

	问题:在一个进程运行一次时间片时,但还未结束,需要插入就绪队列。
	是先插入,还是先判断一些其他进程是否到达。(就绪队列顺序)
	这里采用:先到达,即先刷新PCB状态,在插入运行时间片结束的PCB。

	课本解释:当该进程的时间片耗尽或运行完毕时,系统再次将CRU分配给队首进程(或新到达的紧迫进程)。由此可保证就绪队列
	中的所有进程在一个确定的时间段内,都能够获得一次CPU执行。
	因此:正确答案应该是,新到达的进程放队首。
*/
struct pcb { /* 定义进程控制块PCB */
	char state;//进程状态 就绪 W(Wait)、运行R(Run)、或完成F(Finish)
	int Atime=0;//到达时间,默认同一时间到达
	int ntime;//进程运行时间
	int rtime;//已用CPU时间
	int TF;//是否为就绪队列内的有效PCB,默认有效
	struct pcb* link;
	//新建变量:是否到达的一个状态  
	char name[10];//进程名
}*ready = NULL, * p;
typedef struct pcb PCB;
int h = 0;//执行时间片数
int Time = 0;//CPU运行时间 利用Time记录每个进程的完成时间   (Time-Atime) 是周转时间
float allAvgTime = 0;//累加所有进程的带权周转时间

/* 当该进程的时间片耗尽或运行完毕时,将该进程插入有效就绪队列*/
void sort()
{
	PCB* first, * second;
	if (ready == NULL||ready->TF==0) /*就绪队列为空,或者进程重新插入时,就绪队列有效PCB为0,插入队首*/
	{
		p->link = ready;
		ready = p;
	}
	else /*尾插 只能插入到有效PCB的后面*/
	{
		first = ready;
		second = first->link;
		while (second != NULL&&second->TF==1)
		{
			first = first->link;
			second = second->link;
		}
		p->link = second;
		first->link = p;
	}
}

/*PCB必须按顺序输入,到达时间从小到大。*/
/* 建立进程控制块函数,按顺序插入到就绪队列中*/
void input()
{
	int i, num;
	system("cls"); /*清屏*/
	printf("\n 请输入建立的进程数?");
	scanf("%d", &num);
	for (i = 0; i < num; i++)
	{
		printf("\n 进程号No.%d:\n", i);
		p = getpch(PCB);//申请结构体PCB内存空间
		printf("\n 输入进程名:");
		scanf("%s", &p->name);
		printf("\n 输入进程到达时间:");
		scanf("%d", &p->Atime);
		printf("\n 输入进程运行时间:");
		scanf("%d", &p->ntime);
		p->link = NULL;
		p->state = 'w';
		p->rtime = 0;
		p->TF = 1;
		printf("\n");
		sort(); //调用sort函数,插入p进程进入ready队列
	}
}

/*查看就绪队列中有多少进程*/
int space()
{
	int l = 0; PCB* pr = ready;
	while (pr != NULL)
	{
		l++;
		pr = pr->link;
	}
	return(l);
}

/*建立进程显示函数,用于打印当前进程*/
void disp(PCB* pr)
{
	printf("\n qname \t state \t Atime \t ndtime  runtime  daoda(0/1) \n");
	printf("|%s\t", pr->name);
	printf("|%c\t", pr->state);
	printf("|%d\t", pr->Atime);
	printf("|%d\t", pr->ntime);
	printf("|%d\t", pr->rtime);
	printf("  |%d\t", pr->TF);
	printf("\n");
}

/* 建立进程查看函数 */
void check()
{
	PCB* pr;
	printf("\n **** 当前正在运行的进程是:%s", p->name); /*显示当前运行进程*/
	disp(p);//封装
	pr = ready;
	printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/
	while (pr != NULL)
	{
		disp(pr);//调用打印
		pr = pr->link;
	}
}
/*建立进程撤消函数(进程运行结束,撤消进程)*/
void destroy()
{
	allAvgTime = allAvgTime + (float)(Time - p->Atime) / p->ntime;
	printf("\n 进程 [%s] 已完成.\n周转时间为[%d ms]\n带权周转时间为[%.2f ms]\n", p->name,Time-p->Atime,(float)(Time - p->Atime)/p->ntime);
	free(p);
}

/*在每次调用running中的sort前,刷新PCB的状态(是否到达)*/
void flushed() {

	PCB* traverse, * pre;
	traverse = ready;
	pre = NULL;
	while (traverse != NULL&&traverse->TF==1) {
		//只需将未到达的PCB置为0即可
		if (traverse->Atime > Time) {//不应该是finish时间,应该是CPU执行时间(h*q 比CPU执行时间略大 暂时就这样吧)
			traverse->TF = 0;
		}
			
			//新到达的程序(数组)放就绪队列队头
			//记录(front) 记录第一个0-->1(left)  循环遍历到最后一个0->1(rigth) 记录后面链表(behind  pre->behind)  
			//再将ready置为(left)  
		pre = traverse;
		traverse = traverse->link;
	}

	//本程序只考虑一次改变一个PCB状态(简单)

	if (traverse != NULL&& traverse->Atime <= Time) {
		traverse->TF = 1;
		if (pre != NULL) {
			pre->link = traverse->link;
			traverse->link = ready;
			ready = traverse;
		}
		
	}
}
/* 建立进程就绪函数(进程运行时间到,置就绪状态*/
void running()
{
	(p->rtime)= (p->rtime)+q;
	if (p->rtime >= p->ntime) {
		if (p->rtime == p->ntime) { 
			Time = Time + q;
		}
		else {
			Time = Time + (p->ntime) % q;//未利用完时间片,完成跳出
		}
		p->state = 'F';
		//新建一个周转时间(同一时刻创建,所以周转时间等于完成时间) ,记录完成时间
		// 根据周转时间/服务时间=带权周转时间
		//如果刚好是时间片的整数倍,直接 当前时间片*时间片数 
		//如果不是整数倍 则ntime%时间片+时间片
		destroy(); /* 调用destroy函数*/
	}
	else
	{
		Time = Time + q;//未执行完毕
		p->state = 'w';//就绪
		sort(); /*调用sort函数,重新插入到就绪队列*/
		flushed();//每次都要重新判断是否有PCB到达, 到达直接插入队首.
	}
}


void main() /*主函数*/
{
	int len;
	char ch;
	input();//建立PCB
	len = space();
	flushed();//PCB状态刷新
	while ((len != 0) && (ready != NULL))
	{
		ch = getchar();
		h++;
		printf("\n The execute number:%d \n", h);
		if (ready->TF == 0) {//就绪队列内没有有效PCB
			//这里只需加上CPU空闲时间即可  第一个无效进程的到达时间-上一个完成进程的完成(注意是完成)时间
			//Time= Time+(ready->Atime - Time);
			Time = ready->Atime;

			//将第一个无效PCB改为有效PCB
			ready->TF = 1;
		}
		else {
			p = ready;
			ready = p->link;
			p->link = NULL;
			p->state = 'R';
			check();
			running();
			printf("\n 按任一键继续......");
			ch = getchar();
		}
		
	}
	printf("\n\n 进程已经完成.\n");
	printf("系统的平均带权周转时间为【%.2f ms】", allAvgTime / len);
	ch = getchar();
}

到了这里,关于“时间片轮转”调度算法(C语言)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【进程调度】基于优先级的轮转调度C++实现算法

    在计算机科学领域, 进程调度是操作系统中一个关键的组成部分,它负责协调系统中各个进程的执行顺序,以最大程度地提高系统资源利用率 。在这篇博客中,将深入探讨基于优先级的轮转调度算法,该算法结合了进程的 优先级 和 时间片轮转 的思想,以实现高效的任务执

    2024年01月20日
    浏览(36)
  • 【linux 多线程并发】多任务调度器,调度策略时间片轮转,先进先出,多种实时任务的策略,内核级最高优先级调度策略

    ​ 专栏内容 : 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的

    2024年02月03日
    浏览(45)
  • 操作系统:用C语言实现FCFS(先来先服务),SJF(短作业抢占)和RR(时间片轮转,时间片=1)

       加深对进程调度的理解,熟悉进程调度的不同算法,比较其优劣性。 假如一个系统中有5个进程,它们的到达时间内如表1所示,忽略I/O以及其他开销时间。若分别按先来先服务(FCFS)、抢占的短作业优先(SJF)、时间片轮转(RR,时间片=1)进行CPU调度,请按照上述三个

    2024年02月04日
    浏览(44)
  • 时间片轮转算法(c++)

    操作系统进程调度的基本算法,时间片轮转。 假设cpu只有单核,但是进程很多,最简单就是先来先服务,但是会造成后来的进程等待很久,所以有另一种策略就是每个进程都服务一会,这样就不会出现一个进程长时间得不到服务的情况   (饿死现象),在轮流服务一会的方式中

    2024年02月03日
    浏览(25)
  • 磁盘调度算法例题解析以及C语言实现

    如果当前停留在第122号磁道上,接下来8个磁道按顺序分别是 120,98,4,51,180,195,140,23。请写出最短寻道时间优先和扫描算 法的访问顺序以及各自的平均寻道长度。 最短寻道时间优先算法: SSTF算法选择调度处理的磁道是与当前磁头所在磁道距离最近的磁道,以使每次的寻找时间

    2024年02月12日
    浏览(37)
  • 操作系统进程调度算法(c语言模拟实现)

            前言: 本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解, 完整代码放在文章末尾,欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路: 算法模拟:  最短作业优先调度算法

    2024年02月06日
    浏览(41)
  • 操作系统进程调度算法的模拟实现(c语言版本)

            前言: 本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解, 完整代码放在文章末尾,欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路: 算法模拟:  最短作业优先调度算法

    2024年02月06日
    浏览(44)
  • 先来先服务调度算法(C语言代码实现) 大三操作系统实验

    实验原理: 先来先服务(First Come First Served,FCFS),是一种简单的调度算法,它既适用于作业调度,也适用于进程调度。先来先服务算法是按照作业或进程的到达先后次序来进行调度。当作业调度中采用该算法时,每次调度都是从后备队列中选择一个最先进入该队列中作业,将

    2024年04月16日
    浏览(24)
  • 操作系统实验一模拟优先级调度算法(C语言实现附带详细注释)

    文章目录 优先级调度算法介绍 两种情况 调度算法分类 优先级分类 实验内容与要求 实验步骤 调度算法总流程图  优先级调度算法流程图  实验代码 实验结果         优先级调度算法既可以用于作业调度,又可以用于进程调度。该算法中的优先级用于描述作业或者进程的

    2024年02月01日
    浏览(36)
  • 【操作系统】基于动态优先级的进程调度算法-C语言实现(有代码)

    本文章将会介绍如何编写动态优先级的进程调度算法,并使用从语言实现。 一、什么是动态优先级的调度算法        进程运行一个时间片后,如果进程已占用 CPU时间已达到所需要的运行时间,则撤消该进程;如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包