FreeRTOS入门教程(空闲任务和钩子函数及任务调度算法)

news2025/4/5 20:41:46

文章目录

  • 前言
  • 一、空闲任务概念
  • 二、钩子函数概念
  • 三、任务调度算法
  • 四、任务调度算法实验
    • 1.实验代码
    • 2.是否抢占
    • 3.时间片是否轮转
    • 4.空闲任务让步
  • 总结


前言

本篇文章将带大家学习一下什么是空闲任务以及钩子函数,以及学习FreeRTOS中的任务调度算法,了解在FreeRTOS中任务是如何进行切换调度的。

一、空闲任务概念

空闲任务(Idle Task)是嵌入式实时操作系统(RTOS)中的一种特殊任务。它是系统中优先级最低的任务,并且在系统中没有其他任务需要执行时运行。空闲任务的目的是让处理器在没有其他工作需要执行时保持忙碌状态,从而防止处理器进入空转状态。

空闲任务在RTOS中发挥着重要的作用。当所有其他任务都没有工作要执行时,空闲任务就会运行。它通常执行一些轻量级的操作,如低功耗模式的进入、系统统计信息的更新、调度器的处理等。空闲任务的执行时间应尽量短,以充分利用处理器资源。

空闲任务可以被视为一个后备任务,确保系统始终有任务可以运行,即使没有其他任务就绪。这对于实时系统来说尤为重要,因为实时系统需要对外部事件以及响应用户请求作出快速响应。通过空闲任务,RTOS可以保证系统的连续性和响应性。

在FreeRTOS中,空闲任务是由内核自动创建和管理的。

在使用vTaskStartScheduler开启调度器后会自动的帮我们创建好空闲任务。
在这里插入图片描述

二、钩子函数概念

FreeRTOS 中的钩子函数(Hook Functions)是用户定义的回调函数,用于在 FreeRTOS 内核中特定事件发生时执行自定义的代码。这些钩子函数允许开发者介入 FreeRTOS 的内部操作,以便适应特定的需求、调试或性能分析。

使用钩子函数时需要先开启FreeRTOS中的configUSE_IDLE_HOOK配置宏。

FreeRTOSConfig.h:
在这里插入图片描述

在这里插入图片描述
重新实现钩子函数:

void vApplicationIdleHook( void )
{
	//用户自定义处理
}

三、任务调度算法

调度算法是操作系统中用于确定进程或线程在可用系统资源上执行的顺序和时间分配的一组规则和策略。调度算法的作用是合理地利用系统资源,提高系统的性能、响应性和效率。

调度算法在多任务操作系统中起着重要的作用,它决定了各个任务之间的执行顺序、分配的时间片长度以及资源的分配策略。

在 FreeRTOS 中,调度算法和行为可以通过一些宏配置来决定,包括 configUSE_PREEMPTION、configUSE_TIME_SLICING 和 configIDLE_SHOULD_YIELD。

1.configUSE_PREEMPTION:

这个宏控制是否启用任务抢占(preemption)。如果设置为 1,则允许具有更高优先级的任务中断当前正在执行的任务;如果设置为 0,则不允许任务抢占。
任务抢占允许更高优先级的任务能够立即获得处理器的控制权,以满足实时需求。然而,抢占会引入上下文切换的开销,可能会对性能产生影响。

2.configUSE_TIME_SLICING:

这个宏用于启用或禁用时间片轮转调度(time slicing)。时间片轮转调度是一种机制,当多个任务具有相同优先级并且可运行时,它们会按时间片的方式轮流使用处理器。
如果设置为 1,则启用时间片轮转调度;如果设置为 0,则禁用时间片轮转调度。

3.configIDLE_SHOULD_YIELD:

这个宏用于配置空闲任务是否应该主动让出处理器。当系统没有其他优先级较高的任务需要运行时,空闲任务会获得处理器的控制权。如果设置为 1,则空闲任务在不需要执行任何其他操作时会主动让出处理器;如果设置为 0,则空闲任务不会主动让出处理器。

如果系统中有其他低优先级任务需要执行,让空闲任务主动让出处理器可以提供更好的响应时间和系统性能。

这里使用百问网提供的一张资料图:
在这里插入图片描述

四、任务调度算法实验

1.实验代码

volatile int flagIdleTaskrun = 0;  // 空闲任务运行时flagIdleTaskrun=1
volatile int flagTask1run = 0;     // 任务1运行时flagTask1run=1
volatile int flagTask2run = 0;     // 任务2运行时flagTask2run=1
volatile int flagTask3run = 0;     // 任务3运行时flagTask3run=1

/*-----------------------------------------------------------*/

void vTask1( void *pvParameters )
{
	/* 任务函数的主体一般都是无限循环 */
	for( ;; )
	{
		flagIdleTaskrun = 0;
		flagTask1run = 1;
		flagTask2run = 0;
		flagTask3run = 0;
		
		/* 打印任务的信息 */
		printf("T1\r\n");				
	}
}

void vTask2( void *pvParameters )
{	
	/* 任务函数的主体一般都是无限循环 */
	for( ;; )
	{
		flagIdleTaskrun = 0;
		flagTask1run = 0;
		flagTask2run = 1;
		flagTask3run = 0;
		
		/* 打印任务的信息 */
		printf("T2\r\n");				
	}
}

void vTask3( void *pvParameters )
{	
	const TickType_t xDelay5ms = pdMS_TO_TICKS( 5UL );		
	
	/* 任务函数的主体一般都是无限循环 */
	for( ;; )
	{
		flagIdleTaskrun = 0;
		flagTask1run = 0;
		flagTask2run = 0;
		flagTask3run = 1;
		
		/* 打印任务的信息 */
		printf("T3\r\n");				

		// 如果不休眠的话, 其他任务无法得到执行
		vTaskDelay( xDelay5ms );
	}
}

void vApplicationIdleHook(void)
{
	flagIdleTaskrun = 1;
	flagTask1run = 0;
	flagTask2run = 0;
	flagTask3run = 0;	
	
	/* 故意加入打印让flagIdleTaskrun变为1的时间维持长一点 */
	//printf("Id\r\n");				
}

int main( void )
{
	prvSetupHardware();
	
	xTaskCreate(vTask1, "Task 1", 1000, NULL, 0, NULL);
	xTaskCreate(vTask2, "Task 2", 1000, NULL, 0, NULL);
	xTaskCreate(vTask3, "Task 3", 1000, NULL, 2, NULL);

	/* 启动调度器 */
	vTaskStartScheduler();

	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	return 0;
}

2.是否抢占

抢占:
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configIDLE_SHOULD_YIELD 1
在这里插入图片描述

不抢占:
#define configUSE_PREEMPTION 0
#define configUSE_TIME_SLICING 1
#define configIDLE_SHOULD_YIELD 1

在这里插入图片描述

这里可以发现当配置为抢占的时候,高优先级的任务就绪后就可以直接执行了。

当配置为不可抢占时,任务会一直执行下去,其他任务无法抢占执行权。

3.时间片是否轮转

支持时间片轮转:

#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configIDLE_SHOULD_YIELD 1

在这里插入图片描述

不支持时间片轮转:

#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 0
#define configIDLE_SHOULD_YIELD 1

在这里插入图片描述
当配置为支持时间片轮转时,在Tick中断会引起任务的切换。

高优先级任务就绪时会引起任务切换,高优先级任务不再运行时也会引起任务切
换。可以看到任务3就绪后可以马上执行,它运行完毕后导致任务切换。其他时间没有任务切换,
可以看到任务1、任务2都运行了很长时间。

当 FreeRTOS 配置为支持时间片轮转(即 configUSE_TIME_SLICING 设置为 1)时,任务会按照时间片的方式进行调度。每个任务被分配一个时间片,在时间片用尽之前,如果发生 Tick 中断,则会引起任务切换。

4.空闲任务让步

空闲任务让步
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configIDLE_SHOULD_YIELD 1

在这里插入图片描述

空闲任务不让步
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configIDLE_SHOULD_YIELD 0

在这里插入图片描述
当配置为空闲任务让步时,可以看出空闲任务运行的时间比较短,会让步给其他任务进行执行。

当配置为空闲任务不让步时,可以看出空闲任务运行的时间和任务1,任务2运行的时间差不多,并不会做出让步。

总结

本篇文章就讲解到这里。

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

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

相关文章

常见的7种分布式事务解决方案(2pc,3pc,Tcc,Seta、本地事务....)

一 分布式事务 1.1 分布式事务 在分布式系统中一次操作需要由多个服务协同完成,这种由不同的服务之间通过网络协同完成的事务称为分布式事务。 1.首先满足事务特性:ACID 2.而在分布式环境下,会涉及到多个数据库 总结:分布式事务…

Makefile快速上手

Makefile学习 https://maxwell-lx.vip/basic-usage-make/ https://zhuanlan.zhihu.com/p/92010728 https://zhuanlan.zhihu.com/p/350297509 一、是什么 可以理解为一个自动化的编译脚本,避免繁琐的手动编译过程。有点类似shell脚本。 1.1 从小例子入手 &…

B058-SpringBoot

目录 springboot概念与作用入门案例springboot运行方式热部署配置文件Profile多环境支持整合测试-springboot-testSpringboot-web1.返回json数据2.返回页面(模板技术)thymeleaf1.导入thymeleaf依赖2.模板文件3.controller4.启动类 SSM整合1.导包2.项目目…

【Excel】快速提取某个符号前面的数据内容

【问题描述】 在使用excel整理数据过程中,经常与需要调整数据后,进行使用。 例如凭证导出后,科目列是包含科目编码和科目名称的。 但由于要将数据复制到其他的导入模板上使用,对应的模板只需要科目编码,不需要科目名称…

【管理运筹学】第 5 章 | 整数规划(4,指派问题)

系列文章 【管理运筹学】第 5 章 | 整数规划 (1,问题提出与分支定界法) 【管理运筹学】第 5 章 | 整数规划 (2,割平面法及 0-1 变量的特性) 【管理运筹学】第 5 章 | 整数规划 (3,隐…

Win10怎样取消自动固定到快速访问?

双击桌面上此电脑在菜单栏点击查看在弹出的选项里边选择选项在打开文件资源管理器那里把快速访问改成此电脑在下面隐私部分选择快速访问中显示最近使用文件在快速访问中显示常用文件夹并且清除文件资源管理器记录就行。

调度器/调度程序

一、调度对象 1.让谁运行-调度算法 闲逛进程:无其他就绪进程时,运行闲逛进程;优先级最低,能耗低。 2.运行多长时间-时间片大小 二、调度产生时机 1.创建新进程与进程退出 2.运行进程阻塞 3.I/O中断发生,可能唤醒…

lv5 嵌入式开发-8 信号机制(上)

目录 1 信号机制 2 信号的产生 3 常用信号 4 相关命令 4.1 信号相关命令 kill / killall 4.2 信号发送 – kill / raise 4.3 定时器函数相关函数 – alarm /ualarm/ pause 4.4 信号捕捉:设置信号响应方式 – signal /sigaction,闹钟实现 4.5 子…

CCF CSP认证 历年题目自练Day14

CCF CSP认证 历年题目自练Day14 题目一 小明今天生日,他有n块蛋糕要分给朋友们吃,这n块蛋糕(编号为1到n)的重量分别为a1, a2, …, an。小明想分给每个朋友至少重量为k的蛋糕。小明的朋友们已经排好队准备领蛋糕,对于…

【进阶C语言】动态内存分配

本章大致内容介绍: 1.malloc函数和free函数 2.calloc函数 3.realloc函数 4.常见错误案例 5.笔试题详解 6.柔性数组 一、malloc和free 1.malloc函数 (1)函数原型 函数参数:根据用户的需求需要开辟多大的字节空间&#xff…

nodejs+vue 网上招聘系统elementui

第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:技术背景 5 3.2.2经济可行性 6 3.2.3操作可行性: 6 3.3 项目设计目标与原则 6 3.4系统流程分析 7 3.4.1操作流程 7 3.4.2添加信息流程 8 3.4.3删除信息流程 9 第4章 系统设计 11 …

【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)

文章目录 0. 前言1. Cifar10数据集1.1 Cifar10数据集下载1.2 Cifar10数据集解析 2. LeNet5网络2.1 LeNet5的网络结构2.2 基于PyTorch的LeNet5网络编码 3. LeNet5网络训练及输出验证3.1 LeNet5网络训练3.2 LeNet5网络验证 4. 完整代码4.1 训练代码4.1 验证代码 0. 前言 按照国际…

Spring Boot 常用注解详解:全面指南

Spring Boot 中有许多常用的注解,这些注解用于配置、管理和定义 Spring Boot 应用程序的各个方面。以下是这些注解按大类和小类的方式分类,并附有解释和示例。 一、Spring Boot 核心注解 SpringBootApplication 解释:这是一个组合注解&a…

反射学习笔记

反射学习笔记 一、反射入门案例 在反射中,万物皆对象,方法也是对象。反射可以在不修改源码的情况下,只需修改配置文件,就能实现功能的改变。 实体类 /*** 动物猫类*/ public class Cat {private String name;public void hi()…

openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86

文章目录 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x8684.1 BIOS84.2 操作系统环境设置84.3 网络 openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86 …

大学各个专业介绍

计算机类 五米高考-计算机类 注:此处平均薪酬为毕业五年平均薪酬,薪酬数据仅供参考 来源: 掌上高考 电气类 五米高考-电气类 机械类 五米高考-机械类 电子信息类 五米高考-电子信息类 土木类 五米高考-土木类

Cloudflare进阶技巧:缓存利用最大化

1. 引言 cloudflare我想你应该知道是什么,一家真正意义上免费无限量的CDN,至今未曾有哥们喷它的。当然,在国内的速度确实比较一般,不过这也不能怪它。 CDN最大的特色,我想就是它的缓存功能,达到防攻击&am…

【数据结构】归并排序、基数排序算法的学习知识点总结

目录 1、归并排序 1.1 算法思想 1.2 代码实现 1.3 例题分析 2、基数排序 2.1 算法思想 2.2 代码实现 2.3 例题分析 1、归并排序 1.1 算法思想 归并排序是一种采用分治思想的经典排序算法,通过将待排序数组分成若干个子序列,将每个子序列排序&#xff…

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗

在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用,原则上可…

Ubuntu 20.04部署Promethues

sudo lsb_release -r可以看到操作系统版本是20.04,sudo uname -r可以看到内核版本是5.5.19。 sudo wget -c https://github.com/prometheus/prometheus/releases/download/v2.37.1/prometheus-2.37.1.linux-amd64.tar.gz下载必要的组件。 tar -zxf prometheus-2.…