微型操作系统内核源码详解系列四(4):操作系统调度算法(FreeRTOS内核篇下)

本文主要是介绍微型操作系统内核源码详解系列四(4):操作系统调度算法(FreeRTOS内核篇下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系列一:微型操作系统内核源码详解系列一:rtos内核源码概论篇(以freertos为例)-CSDN博客

系列二:微型操作系统内核源码详解系列二:数据结构和对象篇(以freertos为例)-CSDN博客

系列三:微型操作系统内核源码详解系列三(0):空间存储及内存管理篇(前置篇)-CSDN博客

                微型操作系统内核源码详解系列三(1):任务及切换篇(任务函数定义)-CSDN博客

                微型操作系统内核源码详解系列三(2):任务及切换篇(任务函数定义)-CSDN博客

                微型操作系统内核源码详解系列三(3):任务及切换篇(任务函数定义)-CSDN博客

                微型操作系统内核源码详解系列三(4):arm架构篇-CSDN博客

                微型操作系统内核源码详解系列三(5):进程与线程-CSDN博客

系列四:

 ​​​​​微型操作系统内核源码详解系列四(1):操作系统调度算法(linux0.11版本内核)-CSDN博客

微型操作系统内核源码详解系列四(2):操作系统调度算法(rt-thread内核)-CSDN博客

微型操作系统内核源码详解系列四(3):操作系统调度算法(FreeRTOS内核篇上)-CSDN博客

微型操作系统内核源码详解系列四(4):操作系统调度算法(FreeRTOS内核篇下)-CSDN博客

从前面几篇博客我们学习到了几种不同操作系统的调度算法,其实这些调度算法的核心思想都是可以互相联系的。

下面笔者讲解FreeRTOS根据arm架构指令优化的方法:

其实它跟RTT的图标法思想是类似的,但是对过程进行了简化。

这是另一种选择算法:

让我们先看一下这个指令__clz,这个指令会计算从最高位到第一个1之间的0的个数。参考文章:arm clz指令c语言,协处理器及其他指令之:零计数指令CLZ-CSDN博客

#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )  uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )

让我们回忆一下,在RTT内核篇,为了得到第一个1的位置,我们使用了图表法,计算8个位所有出现情况,根据每个不同的数字,我们利用函数算出来了它对应的第一个1在哪里,这样,我们只要把这个数字作为下标,就能以o(1)的时间复杂度找出来这个数字对应的最高优先级是什么。

这种算法的缺点是,空间资源消耗过大。

现在我们有了这个指令clz,所以我们可以很方便的计算位图中1之前的0的个数,而不用去图表中查找。

先看这个函数:

#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )  

 ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )

它被宏定义为taskRECORD_READY_PRIORITY函数,这其实就是根据就绪任务的优先级,把变量uxTopReadyPriority相关的位置1,与上一篇的通用算法对任务的处理类似,每一个任务被添加到就绪列表时,它对应的位置1,进行延时等其他放弃cpu使用权的活动时,它被移除就绪列表,对应的位置0;这两种算法,一个是更新最高优先级的数字,另一个则是更新对应的位,其实这两个之间有一点细微的差别,就是在移除就绪列表的任务时通用算法不用更新,而指令算法要更新,至于原因,笔者已经在上一篇写了。

对应的函数:

当然,实际上是要确认这个优先级对应的链表是否含有多个任务的,为了方便讲解,笔者默认每个优先级只有一个任务。

现在让我们来到taskSELECT_HIGHEST_PRIORITY_TASK函数:

上面已经讲解过了portGET_HIGHEST_PRIORITY函数,我们通过这个指令获得了最高优先级任务的数字,configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );同理,是断言,用来调试,判断这个链表的长度是否大于0,也就是是否有任务,如果没有,那么这个判断的真值就是0,就会触发这个断言。

listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );

同理,当获取最高优先级,判断优先级上面有任务时,就会把pxCurrentTCB的值更新,它代表下一个要被切换的任务,将会在pendsv中断中完成上下文切换。

综上,FreeRTOS的调度算法算是讲完了,笔者花费众多篇幅将调度器的框架抽象出来,如果读者能够理解FreeRTOS内核的本质其实就是一个调度器的话,那么其实已经差不多理解实时操作系统的核心了。顺着这个主干,那些枝叶都是能够衍生出来的,这也就是为什么笔者要从入口一路切入到调度算法的原因,其他的部分笔者会在之后的篇章陆陆续续更新,不过笔者太懒了,也可能某天就断更了  ʅ(´◔౪◔)ʃ

这篇关于微型操作系统内核源码详解系列四(4):操作系统调度算法(FreeRTOS内核篇下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1059855

相关文章

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Java中的xxl-job调度器线程池工作机制

《Java中的xxl-job调度器线程池工作机制》xxl-job通过快慢线程池分离短时与长时任务,动态降级超时任务至慢池,结合异步触发和资源隔离机制,提升高频调度的性能与稳定性,支撑高并发场景下的可靠... 目录⚙️ 一、调度器线程池的核心设计 二、线程池的工作流程 三、线程池配置参数与优化 四、总结:线程

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo

Python实现中文文本处理与分析程序的示例详解

《Python实现中文文本处理与分析程序的示例详解》在当今信息爆炸的时代,文本数据的处理与分析成为了数据科学领域的重要课题,本文将使用Python开发一款基于Python的中文文本处理与分析程序,希望... 目录一、程序概述二、主要功能解析2.1 文件操作2.2 基础分析2.3 高级分析2.4 可视化2.5

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

Python实现终端清屏的几种方式详解

《Python实现终端清屏的几种方式详解》在使用Python进行终端交互式编程时,我们经常需要清空当前终端屏幕的内容,本文为大家整理了几种常见的实现方法,有需要的小伙伴可以参考下... 目录方法一:使用 `os` 模块调用系统命令方法二:使用 `subprocess` 模块执行命令方法三:打印多个换行符模拟

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、