登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
1
2
/ 2 页
下一页
返回列表
首页
›
业界区
›
安全
›
FreeRTOS-空闲任务prvIdleTask()函数解析
FreeRTOS-空闲任务prvIdleTask()函数解析
[ 复制链接 ]
宁觅波
2025-6-8 12:46:05
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
目录
prvIdleTask()函数
prvCheckTasksWaitingTermination() 函数
prvGetExpectedIdleTime() 函数
以下源码为FreeRTOS v9.0.0版本,不同版本源码可能会有所区别,但实现的逻辑差不多。
需要空闲任务的原因:处理器总是需要代码来执行——所以至少要有一个任务处于运行态。为了保证这一点,当调用vTaskStartScheduler()时,调度器会自动创建一个空闲任务。
空闲任务主要用于处理
待删除任务列表
和
低功耗
,它拥有最低优先级(优先级 0)以保证其不会妨碍具有更高优先级的应用任务进入运行态——当然,没有任何限制说是不能把应用任务创建在与空闲任务相同的优先级上;如果需要的话,你一样可以和空闲任务一起共享优先级,不过这样系统就会运行该同等优先级任务了,不会去运行空闲任务(除非该同等优先级任务被挂起)。
prvIdleTask()函数
/*
这个宏函数 portTASK_FUNCTION() 用于允许编译器特定的语言扩展。
此函数的等效原型为 void prvIdleTask( void *pvParameters );
它实际长这样
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
*/
static portTASK_FUNCTION(prvIdleTask, pvParameters)
{
/* 防止编译器警告的 */
(void)pvParameters;
/*rtos的空闲任务---当调度程序启动时自动创建 */
for (;;)
{
/* 查看是否有任务删除了自己---如果是,则空闲任务负责释放已删除任务的TCB和堆栈
在该函数内实现被删除任务内存资源的释放 */
prvCheckTasksWaitingTermination();
/* 抢占式调度的宏为 0 时需要强制进行任务切换,不然高优先级任务无法及时执行 */
#if (configUSE_PREEMPTION == 0)
{
/* 如果没有使用抢占式调度,那么会强制任务切换,看看是否有其他任务可用。
如果使用了抢占,就不需要这样做,因为任何可用的任务都会自动获得处理器 */
taskYIELD();
}
#endif /* configUSE_PREEMPTION */
/* 使用抢占式调度并且空闲任务应该让出时间片的宏为1的时候,空闲任务需要让出时间片给同等优先级的其他就绪任务,
宏 configIDLE_SHOULD_YIELD 用于使能空闲任务可以被同优先级的任务抢占 */
#if ((configUSE_PREEMPTION == 1) && (configIDLE_SHOULD_YIELD == 1))
{
/* 抢占式调度时,与空闲任务同等优先级的任务将会抢占空闲任务执行并且沿用空闲任务剩余的时间片
获取与空闲任务优先级一样的任务数量,当前空闲任务优先级下的就绪列表有任务,那就进行任务切换,执行这些任务 */
if (listCURRENT_LIST_LENGTH(&(pxReadyTasksLists[tskIDLE_PRIORITY])) > (UBaseType_t)1)
{
taskYIELD();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
/* 空闲任务钩子 */
#if (configUSE_IDLE_HOOK == 1)
{
extern void vApplicationIdleHook(void);
/* 从空闲任务中调用用户定义的函数。这允许应用程序设计人员在不增加单独任务开销的情况下添加后台功能。
注意:vApplicationIdleHook()在任何情况下都不能调用可能阻塞的函数,因为空闲任务不能被阻塞 */
vApplicationIdleHook(); // 空闲任务钩子函数
}
#endif /* configUSE_IDLE_HOOK */
/* 这个条件编译应该使用 != 0 的不等式,而不是等于1。这是为了确保当用户定义的
低功耗模式实现要求将 configUSE_TICKLESS_IDLE 设置为 1 以外的值时调用
portSUPPRESS_TICKS_AND_SLEEP() */
/* 低功耗模式 */
#if (configUSE_TICKLESS_IDLE != 0)
{
TickType_t xExpectedIdleTime; // 预期空闲时间
/* 获取预期空闲时间,即进入低功耗模式多久 */
xExpectedIdleTime = prvGetExpectedIdleTime();
/* 只有进入低功耗时间大于等于最短时长 configEXPECTED_IDLE_TIME_BEFORE_SLEEP
系统才会进入低功耗模式节省资源,此次计算的结果可能不是最终进入低功耗的时长,因为可能受到任务调度的影响 */
if (xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP)
{
vTaskSuspendAll();
{
configASSERT(xNextTaskUnblockTime >= xTickCount);
/* 重新计算进入低功耗模式的时间,此时调度器被挂起,所以本次的计算结果
就是进入响应低功耗模式的时长 */
xExpectedIdleTime = prvGetExpectedIdleTime();
/* 只有进入低功耗时间大于等于该宏,系统才会进入低功耗模式节省资源 */
if (xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP)
{
/* 调试用的 */
traceLOW_POWER_IDLE_BEGIN();
/* 该宏函数就是让MCU进入相应低功耗模式的,传入需要进入低功耗模式的时长 */
portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime);
traceLOW_POWER_IDLE_END();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
(void)xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_TICKLESS_IDLE */
}
}
复制代码
1.调用 prvCheckTasksWaitingTermination() 函数检查是否有任务删除了自己,如果有则在该函数内进行TCB控制块和任务堆栈内存的释放。
2.判断是否有与空闲任务同等优先级的任务存在,如果有并且启用了相关的宏那就进行任务切换,转之去运行该同等优先级的任务。
3.是否启动空闲任务钩子函数,空闲任务构造函数是在空闲任务执行时被调用的函数(类似与回调函数),这允许开发者在不单独增加任务创建的开销情况下执行一些其他动作,比如检测系统处理裕量。
4.是否可以进入低功耗模式,使用函数 prvGetExpectedIdleTime() 获取进入低功耗模式的预期时间,只有大于进入低功耗时间的最短时长才会允许进入低功耗模式。最后通过使用 portSUPPRESS_TICKS_AND_SLEEP 进入低功耗模式。
prvCheckTasksWaitingTermination() 函数
查看是否有任务删除了自己---如果是,则是空闲任务负责释放已删除任务的TCB和堆栈在该函数内实现被删除任务内存资源的释放。
static void prvCheckTasksWaitingTermination(void)
{
/* 这个函数从rtos的空闲任务中调用 */
/* 只有启用了任务删除的宏才会执行该函数 */
#if (INCLUDE_vTaskDelete == 1)
{
BaseType_t xListIsEmpty;
/* 等待清理的被删除任务大于0,说明有任务被删除,需要空闲任务释放内存 */
while (uxDeletedTasksWaitingCleanUp > (UBaseType_t)0U)
{
/* 挂起调度器,挂起调度器会阻止上下文切换,如果调度器被挂起时,中断请求切换上下文,
那么请求将会被挂起。而且只有在调度器恢复(取消挂起)时才会执行 */
vTaskSuspendAll();
{
/* 等待删除列表是否为空,不为空说明需要处理 */
xListIsEmpty = listLIST_IS_EMPTY(&xTasksWaitingTermination);
}
(void)xTaskResumeAll();
/* 待删除任务列表中的任务数量不为 0 */
if (xListIsEmpty == pdFALSE)
{
TCB_t *pxTCB;
taskENTER_CRITICAL();
{
/* 获取等待删除列表中的首个列表项任务控制块进行任务的资源释放 */
pxTCB = (TCB_t *)listGET_OWNER_OF_HEAD_ENTRY((&xTasksWaitingTermination));
(void)uxListRemove(&(pxTCB->xStateListItem));
--uxCurrentNumberOfTasks;
/* 等待清除的删除任务减一 */
--uxDeletedTasksWaitingCleanUp;
}
taskEXIT_CRITICAL();
/* 调用删除任务释放堆栈和TCB内存 */
prvDeleteTCB(pxTCB);
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
#endif /* INCLUDE_vTaskDelete */
}
复制代码
该函数很简单,就是执行被删除任务资源的释放,并更新等待终止列表中已被删除任务的数量。内部通过调用 prvDeleteTCB() 函数进行已删除任务的资源释放。
prvGetExpectedIdleTime() 函数
/* 获取预期空闲时间,即进入低功耗模式多久 */
static TickType_t prvGetExpectedIdleTime(void)
{
TickType_t xReturn;
UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
/* uxHigherPriorityReadyTasks 用于处理 configUSE_PREEMPTION(1使用抢占式内核,0使用协程) 为0的情况,
因为可能有高于空闲优先级任务的任务处于 Ready 状态,即使空闲任务正在运行 */
#if (configUSE_PORT_OPTIMISED_TASK_SELECTION == 0)
{
if (uxTopReadyPriority > tskIDLE_PRIORITY)
{
uxHigherPriorityReadyTasks = pdTRUE;
}
}
#else
{
/* 最低有效位 */
const UBaseType_t uxLeastSignificantBit = (UBaseType_t)0x01;
/* 是否有大于优先级0的任务就绪了,0x01指bit0被置1了,bit0表示优先级0的任务
只要后面不管哪个bit被置1都是大于0x01的,即有更高优先级任务就绪了,所以高优先级
任务标志位设置为 pdTRUE */
if (uxTopReadyPriority > uxLeastSignificantBit)
{
uxHigherPriorityReadyTasks = pdTRUE;
}
}
#endif
/* 如果当前执行的任务优先级大于空闲任务优先级是无法进入低功耗的,低功耗模式是在
空闲任务执行期间进入的 */
if (pxCurrentTCB->uxPriority > tskIDLE_PRIORITY)
{
xReturn = 0;
}
/* 与空闲任务优先级 0 一样的任务数量大于1,也无法进入低功耗,需要转去执行优先级和空闲任务
一样为0的这个任务 */
else if (listCURRENT_LIST_LENGTH(&(pxReadyTasksLists[tskIDLE_PRIORITY])) > 1)
{
xReturn = 0;
}
/* 存在优先级高于空闲任务的就绪任务 */
else if (uxHigherPriorityReadyTasks != pdFALSE)
{
xReturn = 0;
}
else
{
/* 下一个任务解除阻塞时间 - 当前滴答计数器值 = 进入低功耗的时间
在排除了前面这么多种情况之后,就只剩空闲任务在运行,可以进入低功耗
模式了,使用下个任务解除阻塞时间(如50) - 当前计数值(如20) = 30
即可以进入低功耗模式的时间就是30 */
xReturn = xNextTaskUnblockTime - xTickCount;
}
return xReturn;
}
复制代码
该函数主要用于获取即将要进入的低功耗时间,如果当前存在优先级大于空闲任务优先级则无法进入低功耗模式。故将 uxHigherPriorityReadyTasks 标志位置1,最终通过返回 xReturn 来确定进入低功耗模式的时长,如果返回的是0则不会进入低功耗模式。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
FreeRTOS
空闲
任务
prvIdleTask
函数
相关帖子
C++拷贝函数:const与引用的高效实践
开源任务管理工具!一款自托管的全能待办协作工具!
Apache DolphinScheduler任务失败重试机制:像快递重投一样智能
巡店任务易遗漏、整改无跟进,如何开始搭建闭环巡检流程?
S001 【模板】从前缀函数到KMP应用 字符串匹配 字符串周期
文本生成任务评估指标
Apache DolphinScheduler 3.4.1 发布,新增任务分发超时检测
用 C# 写一个完整的 ReAct 智能体:从命令行输入到任务完成的全链路拆解
AI Agent 跑完任务怎么通知你?我写了个微信推送服务
【JavaScript高级编程】拆解函数流水线 上
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
C++拷贝函数:const与引用的高效实践
3
704
申屠梓彤
2026-02-23
安全
开源任务管理工具!一款自托管的全能待办协作工具!
2
318
撒阗奕
2026-02-26
安全
Apache DolphinScheduler任务失败重试机制:像快递重投一样智能
6
866
姘轻拎
2026-02-27
安全
巡店任务易遗漏、整改无跟进,如何开始搭建闭环巡检流程?
4
32
郦惠
2026-03-01
业界
S001 【模板】从前缀函数到KMP应用 字符串匹配 字符串周期
4
285
钦娅芬
2026-03-04
安全
文本生成任务评估指标
0
475
刘凤
2026-03-10
安全
Apache DolphinScheduler 3.4.1 发布,新增任务分发超时检测
0
793
呶募妙
2026-03-13
业界
用 C# 写一个完整的 ReAct 智能体:从命令行输入到任务完成的全链路拆解
0
517
郦惠
2026-03-18
业界
AI Agent 跑完任务怎么通知你?我写了个微信推送服务
0
1012
杭环
2026-03-29
业界
【JavaScript高级编程】拆解函数流水线 上
0
264
姥恫
2026-03-30
回复
(26)
骆贵
2025-10-18 14:52:37
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
yyds。多谢分享
语樊偿
2025-10-29 17:18:26
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
鼓励转贴优秀软件安全工具和文档!
梳踟希
2025-11-14 23:26:01
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
谢谢分享,试用一下
莘度
2025-12-21 09:28:09
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
很好很强大 我过来先占个楼 待编辑
倡粤
2026-1-13 14:27:29
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
分享、互助 让互联网精神温暖你我
柏雅云
2026-1-18 12:36:05
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
喜欢鼓捣这些软件,现在用得少,谢谢分享!
褐洌
2026-1-19 23:25:59
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
鼓励转贴优秀软件安全工具和文档!
喳谍
2026-1-20 08:53:56
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
感谢分享,学习下。
创蟀征
2026-1-25 06:00:42
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
yyds。多谢分享
裆趾针
2026-1-25 12:37:52
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
喜欢鼓捣这些软件,现在用得少,谢谢分享!
喳谍
2026-2-3 06:47:43
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
收藏一下 不知道什么时候能用到
篙菠
2026-2-3 11:25:27
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
前排留名,哈哈哈
福清婉
2026-2-3 23:07:09
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
谢谢分享,辛苦了
劳欣笑
2026-2-8 05:11:57
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
谢谢分享,辛苦了
鞍汉
2026-2-9 13:27:53
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
谢谢楼主提供!
更成痒
2026-2-9 19:10:11
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢分享,学习下。
赖琳芳
2026-2-10 15:22:11
回复
使用道具
举报
照妖镜
程序园永久vip申请,无限下载程序园所有程序/软件/数据/等
yyds。多谢分享
柏雅云
2026-2-11 03:53:08
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢分享,下载保存了,貌似很强大
溜椎干
2026-2-11 14:19:01
回复
使用道具
举报
照妖镜
猛犸象科技工作室:
网站开发,备案域名,渗透,服务器出租,DDOS/CC攻击,TG加粉引流
感谢,下载保存了
下一页 »
1
2
/ 2 页
下一页
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
业界
签约作者
程序园优秀签约作者
发帖
宁觅波
2026-2-11 14:19:01
关注
0
粉丝关注
19
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991125
anyue1937
9994892
kk14977
6845359
4
xiangqian
638210
5
神泱
9537
6
宋子
9883
7
韶又彤
9911
8
诀锺
9036
9
荪俗
9020
10
蓬森莉
9871
查看更多
今日好文热榜
6
host怎么设置,host设置教程
245
2026国内图床深度选型指南:从需求到实测,
874
Claude Code源码泄露:8大隐藏功能曝光
674
没有技术要求,只需5步就能完成数据分析和
388
完整项目实战
764
Python 数据类型:数字、字符串与容器
823
从“救火”到“预判”:AIOps 如何用 AI 重
598
Redis 单线程真的是单线程吗?源码角度全面
426
突发!Claude Code 51万行源码全网裸奔:一
495
使用 OpenSpec + 提示词工程 + Harness 思
528
.NET 进阶之路:异步、并发与内存管理的系
497
Java 中的 实现、泛型
977
Go + Vue 接入行为验证码完整指南
624
Python 面向对象编程:从入门到实践
766
Python 面向对象编程:从入门到实践
540
Mem0:给 AI Agent 装上「长期记忆」
757
Mem0:给 AI Agent 装上「长期记忆」
632
我用 Codex 和 Gemini,做了一个本地桌面版
428
Go + Vue 接入行为验证码完整指南
510
Mem0:给 AI Agent 装上「长期记忆」