RTOS:启动调度器的作用(含源码逐行解读)

news2025/6/1 23:34:48

文章目录

  • 前言
  • 一、启动调度器
  • 二、详细逻辑分析
  • 三、逐行分析
    • 3.1、traceENTER_vTaskStartScheduler
    • 3.2、configASSERT( ( sizeof( UBaseType_t ) * taskBITS_PER_BYTE ) >= configNUMBER_OF_CORES );
    • 3.3、xReturn = prvCreateIdleTasks();
    • 3.4、xTimerCreateTimerTask();
    • 3.5、freertos_tasks_c_additions_init
    • 3.6、portDISABLE_INTERRUPTS
    • 3.7、configSET_TLS_BLOCK
    • 3.8、portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
    • 3.9、traceTASK_SWITCHED_IN 和 traceSTARTING_SCHEDULER
    • 3.10、xPortStartScheduler
    • 3.11、configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
    • 3.12、xIdleTaskHandles
    • 3.13、uxTopUsedPriority
    • 3.14、traceRETURN_vTaskStartScheduler
  • 四、启动调度器的作用


前言

操作系统,在入行嵌入式j接触它之前,感觉那是多么高深、神圣的技术,感觉它是高不可攀的。曾经也幻想过它有多么的复杂,在裸机编程时无数次想去应用这个技术,但无奈,无人指引,以致于每每都会望而却步。如今,也在多种OS的基础上做过各行各业的软件开发,所以想在闲暇之时,将使用过的OS内核软件逐行阅读,以提升自我编程能力、去了解更多软件编程思想。写此专栏文章的目的也仅仅是为了让这个过程留痕。

本文所有代码源于RTOS-Keenel

一、启动调度器

话不多说,直接上源码。
void vTaskStartScheduler( void )
{
    BaseType_t xReturn;

    traceENTER_vTaskStartScheduler();

    #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 )
    {
        /* Sanity check that the UBaseType_t must have greater than or equal to
         * the number of bits as confNUMBER_OF_CORES. */
        configASSERT( ( sizeof( UBaseType_t ) * taskBITS_PER_BYTE ) >= configNUMBER_OF_CORES );
    }
    #endif /* #if ( configUSE_CORE_AFFINITY == 1 ) && ( configNUMBER_OF_CORES > 1 ) */

    xReturn = prvCreateIdleTasks();

    #if ( configUSE_TIMERS == 1 )
    {
        if( xReturn == pdPASS )
        {
            xReturn = xTimerCreateTimerTask();
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
    }
    #endif /* configUSE_TIMERS */

    if( xReturn == pdPASS )
    {
        /* freertos_tasks_c_additions_init() should only be called if the user
         * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
         * the only macro called by the function. */
        #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
        {
            freertos_tasks_c_additions_init();
        }
        #endif

        /* Interrupts are turned off here, to ensure a tick does not occur
         * before or during the call to xPortStartScheduler().  The stacks of
         * the created tasks contain a status word with interrupts switched on
         * so interrupts will automatically get re-enabled when the first task
         * starts to run. */
        portDISABLE_INTERRUPTS();

        #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
        {
            /* Switch C-Runtime's TLS Block to point to the TLS
             * block specific to the task that will run first. */
            configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
        }
        #endif

        xNextTaskUnblockTime = portMAX_DELAY;
        xSchedulerRunning = pdTRUE;
        xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;

        /* If configGENERATE_RUN_TIME_STATS is defined then the following
         * macro must be defined to configure the timer/counter used to generate
         * the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
         * is set to 0 and the following line fails to build then ensure you do not
         * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
         * FreeRTOSConfig.h file. */
        portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();

        traceTASK_SWITCHED_IN();

        traceSTARTING_SCHEDULER( xIdleTaskHandles );

        /* Setting up the timer tick is hardware specific and thus in the
         * portable interface. */

        /* The return value for xPortStartScheduler is not required
         * hence using a void datatype. */
        ( void ) xPortStartScheduler();

        /* In most cases, xPortStartScheduler() will not return. If it
         * returns pdTRUE then there was not enough heap memory available
         * to create either the Idle or the Timer task. If it returned
         * pdFALSE, then the application called xTaskEndScheduler().
         * Most ports don't implement xTaskEndScheduler() as there is
         * nothing to return to. */
    }
    else
    {
        /* This line will only be reached if the kernel could not be started,
         * because there was not enough FreeRTOS heap to create the idle task
         * or the timer task. */
        configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
    }

    /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
     * meaning xIdleTaskHandles are not used anywhere else. */
    ( void ) xIdleTaskHandles;

    /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
     * from getting optimized out as it is no longer used by the kernel. */
    ( void ) uxTopUsedPriority;

    traceRETURN_vTaskStartScheduler();
}

二、详细逻辑分析

用于启动调度器,调度器是操作系统的核心部分,负责决定哪个任务应该运行。

主要步骤如下:

  • 1、调用 prvCreateIdleTasks 函数创建空闲任务。空闲任务是系统中优先级最低的任务,当没有其他任务需要运行时,空闲任务才会运行。
  • 2、如果启用了定时器,调用 xTimerCreateTimerTask 函数创建定时器任务。定时器任务是用于处理定时器事件的任务。
  • 3、如果上述步骤都成功了,就会调用函数 freertos_tasks_c_additions_init 进行一些额外的初始化工作。这个函数是可选的,只是当定义了 FREERTOS_TASKS_C_ADDITIONS_INIT 宏才会调用。
  • 4、禁用中断。这是为了确保在调用 xPortStartScheduler 之前不会发生中断。在创建的任务堆栈中,有一个状态,其中就包括了中断开关的状态。因此,当第一个任务开始运行时,中断会自动被重新启用。
  • 5、如果启用了C运行时的TLS支持,函数会调用 configSET_TLS_BLOCK 函数,将C运行时的TLS块切换到第一个运行的任务的TLS块。
  • 6、初始化一些全局变量
  • 7、如果定义了 configGENERATE_RUN_TIME_STATS 宏,函数会调用 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 宏,配置用于生成运行时间统计的定时器/计数器。
  • 8、调用 xPortStartScheduler 函数启动调度器。
  • 9、如果 xPortStartScheduler 函数返回,那么可能是由于没有足够的堆内存来创建空闲任务或定时器任务,或者应用程序嗲用了 xTaskEndScheduler 函数。在后一种情况下,函数会调用 vPortEndScheduler 函数。

三、逐行分析

3.1、traceENTER_vTaskStartScheduler

用于跟踪和调试的宏。

3.2、configASSERT( ( sizeof( UBaseType_t ) * taskBITS_PER_BYTE ) >= configNUMBER_OF_CORES );

检查 UBaseType_t 类型的位数大于核心数量

3.3、xReturn = prvCreateIdleTasks();

为每个核心创建一个空闲任务。

3.4、xTimerCreateTimerTask();

创建定时器任务。前提 configUSE_TIMERS 是启用了,并且 prvCreateIdleTasks 函数成功创建了空闲任务。

3.5、freertos_tasks_c_additions_init

进行一些额外的初始化工作。

3.6、portDISABLE_INTERRUPTS

禁用中断,是为了确保在调用 xPortStartScheduler 函数之前不会发生中断。在创建的任务的堆栈中,有一个状态字,其中包括中断开关的状态。因此,当第一个任务开始运行时,中断会自动被重新启用。

3.7、configSET_TLS_BLOCK

如果启用了TLS支持(configUSE_C_RUNTIME_TLS_SUPPORT宏打开),那么调用该函数将运行TLS块切换到第一个运行任务的TLS。

3.8、portCONFIGURE_TIMER_FOR_RUN_TIME_STATS

如果定义了 configGENERATE_RUN_TIME_STATS 宏,那么调用 8、portCONFIGURE_TIMER_FOR_RUN_TIME_STATS 宏会配置用于生成运行时间统计的定时器/计数器。

3.9、traceTASK_SWITCHED_IN 和 traceSTARTING_SCHEDULER

用于跟踪和调试。

3.10、xPortStartScheduler

启动调度器。

3.11、configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );

如果 xPortStartScheduler 函数返回异常,那么可能是由于没有足够的堆内存来创建空闲任务或定时器任务。

3.12、xIdleTaskHandles

总是将 INCLUDE_xTaskGetIdleTaskHandle 设置为0,可避免编译器发出警告。意味着 xIdleTaskHandles 未在其他地方调用。

3.13、uxTopUsedPriority

防止被优化掉。

3.14、traceRETURN_vTaskStartScheduler

用于跟踪和调试。

四、启动调度器的作用

  • 1、创建空闲任务,空闲任务是系统中优先级最低的任务,当没有其他任务需要运行时,空闲任务会运行。

  • 2、创建定时器任务,如果启用了定时器,那么就会创建一个定时器任务,用于处理定时器事件。

  • 3、启动调度器,调度器开始运行后,会根据任务的优先级和状态,决定哪个任务应该运行。

  • 4、管理系统资源,如处理器、内存、文件和设备。

    总的来说,该函数主要作用就是启动RTOS的调度器,开始执行任务并管理系统资源。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式开发STM32 -- 江协科技笔记

1.背景介绍及基础认知 8大输入输出 斯密特触发器:高于设定阈值输出高电平,低于设定阈值输出低电平 有关上拉输入、下拉输入、推挽输出、开漏输出、复用开漏输出、复用推挽输出以及浮空输入、模拟输入的区别 1、上拉输入:上拉就是把电位拉高…

[网页五子棋][用户模块]客户端开发(登录功能和注册功能)

文章目录 客户端开发登录功能htmlcsscommon.csslogin.css jQuery引入 jquery 运行程序注册功能 客户端开发 登录功能 html <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport&…

MQTT协议,EMQX部署,MQTTX安装学习

一、MQTT概述 1.什么是MQTT MQTT是一种基于“发布订阅“”模式的消息传输协议。 消息&#xff1a;设备和设备之间传输的数据&#xff0c;或者服务和服务之间要传输的数据。 协议&#xff1a;传输数据时所遵循的规范。 2.常见的通讯模式 &#xff08;1&#xff09;客户端-服…

60天python训练计划----day40

DAY 40 训练和测试的规范写法 知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 一.单通道图…

干泵,干式螺杆真空泵

干式真空泵&#xff1a; 无油干式机械真空泵&#xff08;又简称干式机械泵&#xff09;是指泵能从大气压力下开始抽气&#xff0c;又能将被抽气体直接排到大气中去&#xff0c;泵腔内无油或其他工作介质&#xff0c;而且泵的极限压力与油封式真空泵同等量级或者接近的机械真空泵…

Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(五):语音合成输出与交互增强

Tailwind CSS 实战&#xff0c;基于Kooboo构建AI对话框页面&#xff08;一&#xff09; Tailwind CSS 实战&#xff0c;基于Kooboo构建AI对话框页面&#xff08;二&#xff09;&#xff1a;实现交互功能 Tailwind CSS 实战&#xff0c;基于 Kooboo 构建 AI 对话框页面&#x…

职业本科院校无人机专业人才培养解决方案

2023年的中央经济工作会议强调了以科技创新推动现代化产业体系构建的重要性&#xff0c;并提出发展生物制造、商业航天、低空经济等战略性新兴产业。低空经济&#xff0c;依托民用无人机等低空飞行器&#xff0c;在多场景低空飞行活动的牵引下&#xff0c;正逐步形成一个辐射广…

软件评测机构如何保障质量?检测资质、技术实力缺一不可

软件评测机构在保障软件质量上起着关键作用&#xff0c;对软件行业的健康发展极为关键。它们采用专业的技术手段和严格的评估流程&#xff0c;对软件的运行效果、功能等多方面进行细致的审查&#xff0c;为开发者和使用者提供了客观、公正的参考依据。 检测资质正规软件评测机…

Linux多线程(六)之线程控制4【线程ID及进程地址空间布局】

文章目录 线程ID及进程地址空间布局线程局部存储 线程ID及进程地址空间布局 pthread_ create函数会产生一个线程ID&#xff0c;存放在第一个参数指向的地址中。 该线程ID和前面说的线程ID不是一回事。 前面讲的线程ID属于进程调度的范畴。 ​ 因为线程是轻量级进程&#xff…

1.什么是node.js、npm、vue

一、Node.js 是什么&#xff1f; &#x1f63a; 定义&#xff1a; Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境&#xff0c;让你可以在浏览器之外运行 JavaScript 代码&#xff0c;主要用于服务端开发。 &#x1f63a;从计算机底层说&#xff1a;什么是“运…

Xamarin入门笔记(Xamarin已经被MAUI取代)

初级代码游戏的专栏介绍与文章目录-CSDN博客 Xamarin入门 概述 环境 Android开发环境比较简单&#xff0c;自带模拟器&#xff0c;实体机打开开发者模式即可。 iOS开发环境比较复杂&#xff0c;必须搭配Mac电脑&#xff0c;Windows连接Mac开发可能有问题&#xff08;比如发…

排查Oracle文件打开数过多

Oracle数据库在运行过程中&#xff0c;会打开大量的文件以执行其操作&#xff0c;包括数据文件、控制文件、日志文件等。如果Oracle用户打开的文件数过多&#xff0c;可能会引起系统性能下降。下面将深入分析Oracle用户文件打开数的优化策略&#xff0c;以帮助数据库管理员&…

应用层协议http(无代码版)

目录 认识URL urlencode 和 urldecode HTTP 协议请求与响应格式 HTTP 的请求方法 GET 方法 POST 方法 HTTP 的状态码 HTTP 常见 Header Location 关于 connection 报头 HTTP版本 远程连接服务器工具 setsockopt 我们来学习应用层协议http。 虽然我们说, 应用层协…

8.5 Q1|广州医科大学CHARLS发文 甘油三酯葡萄糖指数累积变化与 0-3期心血管-肾脏-代谢综合征人群中风发生率的相关性

1.第一段-文章基本信息 文章题目&#xff1a;Association between cumulative changes of the triglyceride glucose index and incidence of stroke in a population with cardiovascular-kidney-metabolic syndrome stage 0-3: a nationwide prospective cohort study 中文标…

无人机停机坪运行技术分析!

一、运行方式 1. 自动折叠与展开 部分停机坪采用二次折叠设计&#xff0c;通过传动组件实现自动折叠&#xff0c;缩小体积便于运输&#xff1b;展开后最大化停机面积&#xff0c;适应不同任务需求。例如&#xff0c;珠海双捷科技的专利通过两次折叠使停机坪体积最小化&#x…

【Java Web】速通HTML

参考笔记: JavaWeb 速通HTML_java html页面-CSDN博客 目录 一、前言 1.网页组成 1 结构 2 表现 3 行为 2.HTML入门 1 基本介绍 2 基本结构 3. HTML标签 1 基本说明 2 注意事项 4. HTML概念名词解释 二、HTML常用标签汇总 + 案例演示 1. 字体标签 font (1)定义 (2)案例 2…

在线制作幼教早教行业自适应网站教程

你想知道怎么做自适应网站吗&#xff1f;今天就来教你在线用模板做个幼教早教行业的网站哦。 首先得了解啥是自适应网站。简单说呢&#xff0c;自适应网站就是能自动匹配不同终端设备的网站&#xff0c;像手机、平板、电脑等。那如何做幼早教自适应网站呢&#xff1f; 在乔拓云…

Apptrace:APP安全加速解决方案

2021 年&#xff0c;某知名电商平台在 “618” 大促期间遭遇 DDoS 攻击&#xff0c;支付系统瘫痪近 2 小时&#xff1b;2022 年&#xff0c;一款热门手游在新版本上线时因 CC 攻击导致服务器崩溃。观察发现&#xff0c;电商大促、暑期流量高峰和年末结算期等关键商业周期&#…

Web攻防-SQL注入增删改查HTTP头UAXFFRefererCookie无回显报错

知识点&#xff1a; 1、Web攻防-SQL注入-操作方法&增删改查 2、Web攻防-SQL注入-HTTP头&UA&Cookie 3、Web攻防-SQL注入-HTTP头&XFF&Referer 案例说明&#xff1a; 在应用中&#xff0c;存在增删改查数据的操作&#xff0c;其中SQL语句结构不一导致注入语句…

GoldenDB管理节点zk部署

目录 1、准备阶段 1.1、部署规划 1.2、硬件准备 1.3、软件准备 1.4、网络端口开通 1.5、环境清理 2、实施阶段 2.1、操作系统配置 2.1.1、主机名修改 2.1.2、修改hosts文件 2.1.3、禁用防火墙 2.1.4、禁用selinux 2.1.5、禁用透明大页 2.1.6、资源限制调整 2.1.…