当前位置: 首页 > news >正文

400行程序写一个实时操作系统(十六):操作系统中的调度策略

前言

在前面我们完成了Sparrow的临界区的代码,使用临界区,能够解决常见的并发问题,现在该完善我们的调度算法了。

调度算法在操作系统领域常常是热门的话题。不同的用途将会使用不同的调度策略。在本节,笔者将为大家介绍一些操作系统中的调度算法的知识,加深读者对操作系统的理解。

linux内核中的调度策略

调度策略负责进行任务选择和任务切换,linux内核中的调度基于分时技术:多个进程以“时间多路复用”的方式运行,将时间进行分割,不同段时间运行不同的任务,这段时间被称之为时间片。

进程的分类

linux内核中通常有三类进程:

交互式进程:用于和用户发生交互,对时间不是很敏感,时不时卡一卡也是在用户容许范围内。

批处理进程:在后台运行的进程,不与用户直接接触,例如编译程序和科学计算程序等等。

实时进程:对时间要求非常严格的程序,例如自动控制程序。

进程的抢占

linux内核是抢占式的,也就是说,不同的进程有不同的优先级,如果响应的进程的优先级比当前运行的进程的优先级要高,那么当前的进程就会被响应的进程所抢占。

调度算法

早期linux版本的内核的调度算法比较简单:扫描并且计算所有就绪进程的优先级,然后选择最佳的进程来运行,参考的标准是时间片,时间片大的进程往往优先运行。这一算法的缺点非常明显,就是时间不固定。

当然,到了2.6版本之后,linux内核的调度算法已经复杂到不可想象的程度了,这跟多处理器的出现也有很大的关系,此时,调度选择算法会在固定的时间选出任务执行,以确保CPU的运行速度。

Linux0.11版本调度算法

让我们先看看linux内核0.11版本的调度算法。

img

首先是前几行:

c其实代表的是保存进程时间片的值

next表示下一个进程的序列

i,p都与挂载进程的任务队列有关,i代表数组下标,p是指向队列本身的指针。

img

其实这就是一个很常见的比较大小的算法,首先检查这个进程的状态是不是运行状态,然后进行比较,如果在运行队列里遇到比当前进程时间片大的进程,那么就替换成它,c更改为这个大的进程的时间片,next更改为这个进程的下标。

通过这个比较算法,我们筛选出了队列里时间片最大的任务。接下来就是切换了,如果要切换的进程的时间片没有用完,也就是c>0时,这个while循环会直接结束,程序会跳转到switch这里,这就是进程切换的函数。

img

如果这个优先级高的进程的时间片已经用完了,也就是c=.=0时,会进入for循环,这是对时间片的重新分配。因为我们从前面的排序已经知道,c就是被筛选出来的最大的时间片,如果c==0,意味着所有的进程都没有了时间片。

上面的for循环,其实就是根据优先级的大小来调整时间片的大小,最后每一个进程counter的值=原先值/2 +优先级。

可能读者还会疑惑,为什么要加上*p->counter>>1呢?位于运行状态的进程的时间片不是都为0了吗?

进程不止一种状态,显然,还在被阻塞的任务时间片肯定不为0啊,虽然运行状态的进程最终时间片都等于自身优先级的大小,但是阻塞任务就要考虑原先的时间片了,对原先时间片除以2,这是对平均时间片的综合考虑的结果,时间片过短,切换的开销会变大,时间片过长,进程看起来就不会是并行的。

现在让我们来到switch_to函数:

img

在前文笔者简单讨论过进程的上下文切换,因为进程之间隔绝了资源,这往往意味着切换的步骤会变得简单一些,从代码中可以看出,主要是TSS(一个保存进程状态信息的结构体)的切换,但是在FreeRTOS中,则主要是对arm寄存器的操作,因为进程切换是所有的资源都进行了改变,而线程的切换则是在原有的资源上修修改改,本质是任务栈的切换。

通过schedule和switch_to两个函数,我们知道了linux0.11版本是如何进行调度的,schedule负责时间片的分配和进程的选择,switch_to负责进程的切换。

操作系统的调度器本质就是在进行选择和切换。

现在该来到常见的RTOS内核了

FreeRTOS的调度算法

让我们看看tasks.c文件中的这几行代码:

img

prvAddTaskToReadyList函数在每个任务在添加到就绪列表时都会执行,它会与uxTopReadyPriority进行比较,然后uxTopReadyPriority记录两者中的较大者不断的对每一个新添加进来的任务优先级进行比较,这其实就是在找出最大的优先级

这样做,遍历时就能直接找到优先级最高的线程。

img

顺便一提,FreeRTOS中的任务优先级跟我们在mcu中学习到的中断优先级判断是不一样的,也跟RTT和uc/os不一样,mcu中的中断优先级是数字越小,优先级越大,RTT和uc/os的任务优先级也是这样,但FreeRTOS中是任务优先级的数字越大,优先级越大。

img

taskSELECT_HIGHEST_PRIORITY_TASK就是通用的选择算法的具体函数了,先对uxTopReadyPriority的值进行保存。

configASSERT笔者之前提过,是断言,用来debug,如果uxTopPriority小于0,会触发它。

每一个优先级都有一个特定的链表,while判断就绪链表的这个优先级是否有任务挂载在上面,如果没有,就继续找下一个优先级的链表,也就是–uxTopPriority。

uxTopPriority被设定为是代表最大优先级的数字,自减操作代表从就绪列表最后一个链表(优先级最高的链表)开始查找,直到找到任务链表不为空的优先级任务,那么这个任务肯定也是所有任务中优先级最大的任务。

然后获取这个任务的TCB并更新pxCurrentTCB(切换的具体函数),最后更新uxTopReadyPriority的值。

rt-thread内核的调度算法

rt-thread是一个国产RTOS,和sylixOS这些OS一样,也是头部RTOS了,不过在国内的开源领域确实是当之无愧的第一RTOS。

它是一个偏linux的RTOS,而且用面向对象的思想开发的,非常有特色。

笔者决定再讲一讲rtt的选择算法,因为这种算法很常见,用途也非常广泛。

img

img

RTT使用的是查表法,让笔者简单介绍一下这种策略的思想。

我们要查找一个链表中优先级最高的任务,最简便的做法就是for循环,一个个遍历比较,找到优先级最高的任务,这种做法很简便,缺点是复杂度过高,达到了o(n),查询的时间很长。那么有没有使复杂度为1的方法呢?

于是RTT使用了空间换时间的策略。

假设我们有八个优先级,用八个位来表示它们。任务优先级为多少,那么就在哪个位置1。

例如,task1优先级为5,那么优先级的数字就是00010000。

在实时操作系统中,优先级数字越小,优先级越高,那么这个任务代表的1更靠近右侧。

既然知道了这些,那么,把所有8个位的组合都列出来,判断每一个不同的数字最低位的1在哪个位,然后直接查询,不就可以知道任务的优先级最高是多少吗?然后顺着优先级,去执行对应的任务。

img

通过这个函数,可以将prioritynum最低位的1的位置打印出来。这个函数比较简单,就是循环遍历0到255,也就是00000000到11111111,让每一个数依次右移最多八位,找到最低位的1。prioritynum右移后,会与1进行与运算,也就是说,除非右移后的数最低位是1,否则都会进行下一轮循环,直到找到最低位的1并且打印;随后程序又会跳出内层循环进行下一个prioritynum的运算。

运行结果:

img

通过这个数组,我们可以可以将prioritynum作为数组下标查询最高优先级。这其实就是一种哈希算法的思想,用特定的数字映射特定的优先级。

这种算法缺点也十分明显,就是数组占用空间太大了,一个int就要4个字节,上面的例子是优先级为8位,如果优先级有32位呢?那么占用空间将会达到:4*2的32次方个字节。

img

为了解决这个问题,RTT内核使用了四个表,每个表对应8个位,算法也很简洁,先读最低八位的值,判断是否为0,不为0说明优先级肯定在最低八位中,然后直接查表即可。可能有读者好奇为什么要加上1,其实观察就会发现,这个表的第一个0,是在循环之前手动打印的,否则没有256个数,为了避免与32位全为0冲突,所以加上了1。

简单来说,笔者手动让数组里的所有数向后移动了一位,那么相应的,把prioritynum作为下标读取表里的数,也要往后面移动一位。

如果最低八位没有,那就到次八位找,同样先判断是否在次八位中,如果在,那么右移八位然后查表,因为进行了右移操作,所以返回值要在最低八位的返回值的基础加上8。

剩下两个同理,留给读者自己分析了。

总的来说,这种基于哈希思想的查表法应用十分广泛,采用空间换时间的策略,具有一定的学习价值,如果某些程序对查询的时间要求比较高,可以尝试用查表策略代替之前的遍历策略。

总结

笔者介绍了linux内核、FreeRTOS、RT-Thread的调度策略和算法,旨在加深读者对操作系统的理解。当然,本来这些内容应该分成几篇不同的文章细细讲解的,不过笔者还是决定全部放在一篇。

一方面是考虑到放在同一篇文章里更加全面系统,另一方面是考虑到Sparrow的文章数量如果过多了,比如更成了四五十篇。

那么笔者相信屏幕前的读者一定没什么兴趣看下去了。所以笔者还是决定追求简洁明了,不更那么多废话。

Sparrow的教程更到这里,其实已经快接近尾声了。更完调度算法,再更完定时器阻塞延时后,就结束了。

一步步跟着教程实现Sparrow RTOS的小伙伴们,一路看到这里,不知道是否有所收获?

相关文章:

400行程序写一个实时操作系统(十六):操作系统中的调度策略

前言 在前面我们完成了Sparrow的临界区的代码,使用临界区,能够解决常见的并发问题,现在该完善我们的调度算法了。 调度算法在操作系统领域常常是热门的话题。不同的用途将会使用不同的调度策略。在本节,笔者将为大家介绍一些操作…...

从安灯系统看汽车零部件工厂的智能制造转型

在当今快速发展的制造业领域,汽车零部件工厂正面临着日益激烈的市场竞争和不断提高的客户需求。为了在竞争中脱颖而出,实现可持续发展,许多汽车零部件工厂纷纷踏上智能制造转型之路。而安灯系统作为一种重要的生产管理工具,在这场…...

SwiftUI(三)- 渐变、实心形状和视图背景

引言 在现代的应用的UI设计中,渐变和形状背景为界面带来了丰富的层次与视觉效果,而SwiftUI提供了一系列简单且强大的API,可以轻松实现这些效果。在这篇文章中,我们将介绍SwiftUI中的渐变、实心形状和视图背景的基础用法&#xff…...

RK3568-ota升级

ota升级 OTA(Over-the-Air)即空间下载技术。 OTA 升级是 Android 系统提供的标准软件升级方式。它功能强大,可以无损失升级系统,主要通过网络,例如 WIFI、3G/4G 自动下载 OTA 升级包、自动升级,也支持通过…...

GR-ConvNet代码详解

GR-ConvNet代码详解 文章目录 GR-ConvNet代码详解前言一、utils1.dataset_processing1.image.py1.Iamge类2.DepthImage类3.WidthImage类 2.grasp.py1. _gr_text_to_no()方法2.GraspRectangles类3.GraspRectangle类3.Grasp类4.detect_grasps方法 3.generate_cornell_depth.py4.e…...

Excel自带傅里叶分析数据处理——归一化处理

在Excel工具中,默认情况下数据处理---傅里叶分析通常不进行归一化处理,需要用户手动进行归一化处理。 (1)傅里叶变换的原理 傅里叶变换将时域信号转换为频域信号,输出的是复数形式的频率分量,包含了幅值和…...

Centos7.6版本安装mysql详细步骤

操作步骤: 1.下载Linux版本Mysql并上传至linux系统中 2.解压mysql并查询系统中是否有相关软件存在以及配置mysql,启动mysql tar -zxvf mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz tar -zxvf mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz rpm -qa|grep mysql ##查…...

寄宿学校:为自闭症儿童提供全面的教育和关爱

在这个多彩的世界里,每一个生命都值得被温柔以待,每一颗心灵都值得被悉心呵护。然而,自闭症儿童这一特殊群体,他们的世界却常常被误解和忽视。幸运的是,有一种教育模式——寄宿学校,正为这些孩子打开了一扇…...

LLaMA Factory环境配置

LLaMA-Factory官方文档 安装正确的torch和cuda版本 参考: PyTorch 报错解决 1.ImportError: /usr/lib/x86_64-linux-gnu/libstdc.so.6: version GLIBCXX_3.4.29 not found 参考这个解决:丝滑解决ImportError: /usr/lib/x86_64-linux-gnu/libstdc.s…...

STM32实现毫秒级时间同步

提起“时间同步”这个概念,大家可能很陌生。一时间搞不清楚是什么意思。 我理解“时间同步”可以解决多个传感器采集数据不同时的问题,让多个传感器同时采集数据。 打个比方。两个人走路,都是100毫秒走一步(频率相同是前提&…...

瑞吉外卖之com.fasterxml.jackson.dataformat.cbor.CBORFactor相关报错

1.报错:Error creating bean with name routerFunctionMapping defined in class path resource [com/itheima/reggie/config/WebMvcConfig.class]: Failed to instantiate [org.springframework.web.servlet.function.support.RouterFunctionMapping]: Factory met…...

CSS - grid制作表格

1. grid-template-columns:网格布局中的列的数量,也可以设置列的宽度 .grid-container {display: grid;grid-template-columns: 80px 200px auto 40px; }.grid-container {display: grid;grid-template-columns: auto auto auto auto;//表示所有列的宽度…...

【pip】 的换源(临时换源和永久换源)

【pip】 的换源(临时换源和永久换源) 一、临时换源二、永久换源三、Linux换源四、Windows换源 一、临时换源 临时换源只需要在pip安装包时,加上一个-i参数后接源的url即可: 临时换源: 清华源 pip3 install markdown…...

Kaggle 数据集dogs-vs-cats的错误

如果你想用kaggle数据集dogs-vs-cats做深度学习数据,可能会遇到数据bug,大概类似于下面的错误: UnidentifiedImageError: cannot identify image file 其原因不是你的程序有问题,而是数据集本身还有bug: cats/666.jpgdogs/11702.jpg 预览一下…...

【网络原理】网络地址转换----NAT技术详解

💐个人主页:初晴~ 📚相关专栏:计算机网络那些事 我们在 IP协议 一文中介绍过,由于IPv4协议中 IP地址只有32位,导致最多只能表示 42亿9千万个IP地址。但我们需要通过IP地址来标识网络上的每一个设备&#x…...

React怎么创建虚拟dom和挂载到页面

1、🍟你可以直接下载本节配套的资源代码,然后导入vscode看效果,也可以跟着教程一点一点敲,都是没问题的。 2、🤔怎么运行本节代码? 很简单,随便找个浏览器打开index.html即可。💕 代…...

kafka-console-ui的简介及安装使用

kafka-console-ui的简介及安装使用 一、kafka-console-ui的简介二、安装kafka-console-ui2.1 源码安装2.2 docker安装 三、kafka-console-ui功能使用3.1、功能特性3.2、 功能介绍3.2.1 集群3.2.2 topic3.2.3 消费组3.2.4 Acl3.2.5 运维 一、kafka-console-ui的简介 kafka-cons…...

git 的分支管理详解

Git 的分支管理是其强大功能之一,允许开发者在同一代码库中并行开发多个特性或修复 bug,而不干扰主分支的代码。下面是对 Git 分支管理的详解: 1. 查看分支 查看所有分支 git branch # 查看本地分支 git branch -r # 查看远程分支 git br…...

w003基于Springboot的图书个性化推荐系统的设计与实现

🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...

医院信息化与智能化系统(6)

医院信息化与智能化系统(6) 这里只描述对应过程,和可能遇到的问题及解决办法以及对应的参考链接,并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图,可以试试PlantUML,告诉GPT你的文件结构,让他给你对应的…...

前端学习---(6)js基础--4

Promise Promise 是异步编程的一种新的解决方案和规范。 Promise优点: 1、可以很好地解决ES5中的回调地狱的问题(避免了层层嵌套的回调函数)。 2、统一规范、语法简洁、可读性和和可维护性强。 3、Promise 对象提供了简洁的 API,使得管理异步…...

241026-RHEL如何以root身份卸载Docker

在 RHEL 8.8 中,以 root 身份卸载 Docker 可以通过以下步骤完成: 停止 Docker 服务(如果已启动): sudo systemctl stop docker删除 Docker 包: 运行以下命令卸载 Docker 引擎及其依赖包(docker-…...

iPhone当U盘使用的方法 - iTunes共享文件夹无法复制到电脑怎么办 - 如何100%写入读出

效果图 从iPhone复制文件夹到windows电脑 步骤windows 打开iTunes通过USB连接iPhone和电脑手机允许授权iTunes中点击手机图标,进入到点击左边“文件共享”,在右边随便选择一个App(随意...)写入U盘:拖动电脑的文件&am…...

jenkins ssh 免密报错Host key verification failed.

jenkins 发布项目,ssh连接远程服务器时报错:Host key verification failed. 解决: 原因是生成的sshkey不是用的jenkins用户,所以切换用户到:jenkins重新生成sshkey su jenkins ssh-keygen -t rsa ssh-copy-id -i ~/…...

智能科学与技术(一级学科)介绍

智能科学与技术:探索智能的边界与未来 智能科学与技术的起源与发展学科定位与内涵学科范围与研究方向培养目标相关学科 在当今这个信息爆炸的时代,人工智能(AI)已经成为科技创新的重要驱动力。随着技术的不断进步,智能…...

iOS调试真机出现的 “__llvm_profile_initialize“ 错误

一、错误形式&#xff1a; app启动就崩溃&#xff0c;如下&#xff1a; Demo__llvm_profile_initialize:0x1045f7ab0 <0>: stp x20, x19, [sp, #-0x20]!0x1045f7ab4 <4>: stp x29, x30, [sp, #0x10]0x1045f7ab8 <8>: add x29, sp, #0x100x1…...

Android SELinux——neverallow问题处理(十六)

上一篇我们介绍了通过添加允许策略处理问题,这里我们主要来看一些 neverallow 策略问题该怎么处理。 一、neverallow介绍 遇到 neverallow 规则问题,千万别急着去注释/剔除里面原有的规则(原生的尽量别动)。增加 allow 规则是常见的解决办法,但是随着 android 版本的升级…...

Vue 关于路由

关于路由 路由的模式与区别 路由的两种模式&#xff1a; hashhistory 区别&#xff1a; 表象不同 hash 模式中&#xff0c;在地址里以 /#/ 分隔&#xff1b;history 模式中&#xff0c;地址里以 / 分隔。关于找不到当前页面发送请求的问题 history 模式会给后端发送一次请…...

香港海洋投资启动创新海洋牧场,领航全球海洋经济

香港&#xff0c;这座国际大都市&#xff0c;以其独特的地理位置和深厚的海洋文化底蕴&#xff0c;再次站在了全球海洋经济发展的前沿。近日&#xff0c;香港海洋投资发展有限公司&#xff08;以下简称“香港海洋投资”&#xff09;在万众瞩目中&#xff0c;正式宣布启动其创新…...

C/C++ 每日一练:二分查找

二分查找是一种高效的查找算法&#xff0c;用于在有序数组中定位目标元素的位置。它的核心思想是每次查找时将范围缩小一半。 题目要求 实现一个二分查找算法。给定一个递增排序的整型数组 arr 和一个目标值 target&#xff0c;编写一个函数 binarySearch&#xff0c;若 targe…...

杭州网站设计工作室/河北百度seo软件

没有相关的视频教程及相关的学习线路&#xff0c;学起来是一件很费劲的事情&#xff0c;还有很多人从网上及其它渠道购买视频&#xff0c;这些视频资料大多是盗版&#xff0c;上当受骗的人不在少数。为此千锋小编呕心沥血整理了这套零基础全套Linux云计算教程&#xff0c;不管是…...

南昌网站建设服务器/成都网站建设公司排名

转自 http://k.sina.com.cn/article_6367168142_17b83468e001005yrv.html 有振动 就有特征值 今天&#xff0c;超模君看到了一句神翻译&#xff1a; 吓得超模君马上放下手中的苹果手机&#xff0c;来码字了&#xff01;之前有模友说想知道矩阵的特征值和特征向量的意义&#…...

description+wordpress/销售平台排名

在上一篇(博客园的神回复&#xff0c;一起看看那些IT男的神回复[连载][一])中(ps: 这篇博客之所以改名是因为这次的神回复里有程序媛&#xff0c;所以用IT男不太合适)&#xff0c;博客园神回复还是挺受欢迎的&#xff0c;上一篇博客的神回复取材均来自博问区&#xff0c;在这篇…...

ipfs做网站/重大新闻事件2023

当您在使用LC-MS/MS进样测试的过程中出现目标物未出峰的问题时&#xff0c;如果系统配置内有TUV等紫外检测器&#xff0c;可通过对比紫外色谱图数据是否正常来快速排查问题是发生在LC侧还是MS侧。可参考以下步骤快速排查。LC端1、检查样品的前处理是否正确&#xff1f;如溶解样…...

谷秋精品课程网站建设软件/百度怎么推广自己的信息

1.简述编译型与解释型语言的区别&#xff0c;且分别列出你知道的哪些语言属于编译型&#xff0c;哪些属于解释型。 答: 编译型语言&#xff1a; 使用专门的编译器&#xff0c;针对特定的平台&#xff0c;将高级语言源代码一次性的编译成可被该平台硬件执行的机器码&#xff0c;…...

网站是否必须做认证/国外广告联盟平台

摘要&#xff1a;单日总数据处理量超 10 万亿&#xff0c;峰值大概超过每秒 3 亿&#xff0c;OPPO 大数据平台研发负责人张俊揭秘 OPPO 基于 Apache Flink 构建实时数仓的实践&#xff0c;内容分为以下四个方面&#xff1a;建设背景顶层设计落地实践未来展望重要&#xff1a;公…...