0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

减少RTOS中的任务切换

星星科技指导员 来源:嵌入式计算设计 作者:Micro Digital 2022-06-29 09:28 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

任务切换是多任务处理的全部内容。然而,由于以下原因,太多可能会破坏:

它增加了 RTOS 开销

它增加了功耗

它降低了响应能力,尤其是低优先级任务

它增加了调试的复杂性

它可能会导致错误

它可以抑制未来的扩张

因为一个好的 RTOS 在低端 50 MHz Cortex-M3 上每秒可以实现大约 50,000 次任务切换,所以第一个问题对于大多数系统来说可能并不重要。然而,对于电池供电的设备,即使是很小的效率改进也很重要。设备用户可能会注意到低优先级人机界面任务的响应速度降低。不必要的任务切换会混淆已经很复杂的调试过程,因此如果没有其他原因的话,也是不可取的。

第五个原因尤为重要。如果您没有意识到可能会发生任务切换,那么事情可能不会总是按照预期的顺序发生。这可能会导致难以找到的零星错误。最后,随着新功能的添加,空闲时间可能会变得很宝贵,尤其是在处理器性能刚开始的时候。有充分的理由减少过多的任务切换。让我们看几个。

优先提升

一种流行的方法是在选择运行时自动提高任务的优先级。这在以下示例中显示:

void sys_init(void) {

TCB_PTR t2a; // task a of priority 2

t2a = smx_TaskCreate(t2a_main, PRI_2, 500, SMX_FL_NONE, “t2a”);

smx_TaskHook(t2a, t2a_entry, t2a_exit);

smx_TaskStart(t2a);

}

void t2a_entry(void) {

smx_TaskBump(self, 3);

}

void t2a_exit(void) {

smx_TaskBump(self, 2);

}

void t2a_main(void) {

while (1) {

// perform t2a function at priority 3

}

}

在此示例中,t2a_enter() 由调度程序透明地调用,在 t2a 恢复之前,并且 t2a_exit() 在 t2a 暂停之后类似地调用。t2a_enter() 将 t2a 移动到就绪队列级别 3 的前面并将其优先级提高到 3。t2a_exit() 将 t2a 移动到就绪队列级别 2 的末尾并将其优先级降低到 2。因此,t2a 不能被 a 抢占运行时的优先级 3 任务。但是具有更高优先级的任务可以抢占 t2a。在这种情况下,t2a 将回到优先级 2,从而允许任何等待优先级 3 的任务接下来运行。

这种方法很有吸引力,因为一旦 t2a 开始运行,就应该允许它结束。但是,您可能想知道为什么不将 t2a 列为优先级 3 的任务。优先级提升的优点是所有优先级为 3 的任务将在 t2a 允许开始之前运行。然后它成为其中之一。这在三种情况下是有意义的:

t2a 是一个简短的任务

t2a 是一个重型切换器

t2a 是超级用户

如果 t2a 是一项很长的任务,那么将其提升到优先级 3 并不是一个好主意,因为它会影响真正的优先级 3 任务的响应能力。所以,t2a 应该很短。

重型切换器的一个例子是浮点任务,与定点任务相比,它必须保存和恢复额外的 32 个寄存器。另一个例子是通过缓存从慢速内存执行的任务。然后,由于新任务使用不同的代码和变量,重度切换表现为缓存未命中和重新加载。即使在缓存环境中,提升的任务也应该很短。

如果 t2a 以比其他任务更高的功率级别运行(例如,它在运行时打开外围设备),则显然将其运行时间最小化是有益的,假设节能很重要。这是优先级提升的一个很好的用途。

除了优先级反转之外,优先级提升的另一个缺点是它增加了使用它的任务的切换开销。对于上面的示例,任务切换从每秒 50,000 次下降到 26,000 次,这不是问题。

任务锁定

任务锁定是防止不必要的任务切换的另一种方法。以下示例说明了这一点:

TCB_PTR t2a, t3a; // tasks

SCB_PTR sa; // semaphore

void t3a-main(void) {

smx_SemTest(sa);

// do something

}

void t2a-main(void) {

smx_SemSignal(sa);

}

这个例子除了说明隐藏的任务切换之外没有任何用处。由于 t3a 具有更高的优先级,它首先运行,然后等待信号量,sa。然后 t2a 运行并向 sa 发出信号。t2a 并没有像预期的那样停止,而是立即被 t3a 抢占,它做某事,然后停止。然后,t2a 再次运行,除了停止之外什么都不做。您现在可以看到这是一个浪费的任务切换。可以而且应该通过以下方式加以预防:

void t2a-main(void) {

smx_TaskLock();

smx_SemSignal(sa);

}

现在,在 t2a 停止并释放其锁定之前,t3a 无法抢占。请注意,这实际上是调度程序锁定,但我更喜欢称它为任务锁定,因为这更能描述它的作用。

更少的优先级

如果你发现你的系统做了太多的任务切换,最好简单地减少优先级的数量。为此,您显然需要一个允许任务共享优先级的 RTOS。假设您有这样的 RTOS,下一步是重新考虑相关的任务优先级。

当一项任务一直在等待时,它的紧迫性就会增加。降低优先级意味着可能已经抢占它的任务,从而使其等待更长时间,现在将在它之后运行。较低的优先级实际上可以实现更流畅的操作,以及减少不必要的任务切换。

试图过度控制活动而不是让它们自然发生是一种常见的冲动。不太有力的控制可能更能适应不可预见的情况,因此可能会产生更坚固的解决方案。值得一试。

循环调度

在降低优先级的过程中,引入相同优先级的任务的循环调度可能会有所帮助。这可以按如下方式完成:

void t2a_main(void) {

while (smx_TestSem(sa)) {

// do function a

smx_TaskBump(self, NO_PRI_CHG);

}

}

void t2b_main(void) {

while (smx_TestSem(sb)) {

// do function b

smx_TaskBump(self, NO_PRI_CHG);

}

}

当每个任务完成一些工作时,它会将自己撞到就绪队列级别 2 的末尾,以便其他任务可以运行,如果它有工作的话。如果两个任务都没有工作,则两者都将在各自的信号量上挂起,并且可以运行优先级较低的任务。当然,更高优先级的任务可以随时抢占 t2a 和 t2b。在这个例子中,这两个任务可能大部分时间都在等待工作。但是当他们的工作量增加时,他们会交替工作,从而公平地关注所有客户。

不可抢占的任务

通常一次性任务(没有像普通任务那样的内部循环)非常短,使它们不可抢占是有意义的,如下所示:

TCB_PTR t2a;

t2a = smx_TaskCreate(t2a_main, PRI_2, 0, SMX_FL_LOCK, “t2a”);

smx_TaskStart(t2a);

void t2a_main(void) {

// do something simple and stop

}

因为 t2a 是在创建时设置了它的 start-locked 标志,所以它在开始运行时将被锁定,因此在它停止或自行解锁之前是不可抢占的。这类任务非常适合更改关键控制结构之类的事情,因此您不希望它们被抢占。如果这样的任务要等待某个东西,它就会失去它的锁,从而变成可抢占的。

在许多情况下,优先级提升对于提高系统性能很有用。然而,更简单的方法,如任务锁定、降低优先级、循环调度和使用非抢占式任务在某些情况下也很有效。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5620

    浏览量

    130423
  • RTOS
    +关注

    关注

    25

    文章

    870

    浏览量

    123215
  • 电池
    +关注

    关注

    85

    文章

    11614

    浏览量

    144554
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    RT-Thread任务+消息订阅管理框架软件包:thread_manager+event_loop

    一.有个简单的问题(什么是爱情)为什么开源RTOS都只将我们送到Main?却没有一个开源的任务管理+消息订阅框架+延时消息处理框架。就像LVGL好像没有开源的类似于手表功能页面切换框架。上篇文章有个
    的头像 发表于 04-19 15:39 4602次阅读
    RT-Thread<b class='flag-5'>任务</b>+消息订阅管理框架软件包:thread_manager+event_loop

    如何在Zephyr RTOS实现延时和计时函数

    在实时操作系统(RTOS,时间管理是核心功能之一。无论是任务调度、超时控制,还是周期性事件,延时和计时机制都扮演着至关重要的角色。Zephyr RTOS作为一个轻量级、模块化的开源
    的头像 发表于 12-26 10:32 6125次阅读
    如何在Zephyr <b class='flag-5'>RTOS</b><b class='flag-5'>中</b>实现延时和计时函数

    RTOS在嵌入式开发的作用

    嵌入式系统,有很多方式实现任务调度。功能有限的小系统,无限循环足够实现系统功能。当软件设计变得庞大且复杂时,设计师应该考虑使用RTOS(实时操作系统)。 下面给大家分享使用
    发表于 12-26 07:53

    使用RTOS时需要注意的几点内容分享

    RTOS产品代码少和速度快,现在RTOS还提升了一致性。RTOS除能很快完成任务外,还能保证很好地完成任务。 在许多应用
    发表于 12-23 06:34

    嵌入式基础知识-系统调度

    等待的事件发生。 4、RTOS任务切换 RTOS(Real Time Operating System),实时操作系统,指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,调
    发表于 12-16 08:15

    选择RTOS的要点

    选择RTOS。大多数RTOS产品代码少和速度快,现在RTOS还提升了一致性。RTOS除能很快完成任务外,还能保证很好地完成
    发表于 12-12 08:00

    如何在 RTOS 处理微控制器的低功耗特性

    简单讨论一下设计思路,更详细的设计,需要查阅所使用的 RTOS 相关文档资料。RTOS 一般采用基于时间片轮转的抢占式任务调度机制,在实际应用过程,一般的低功耗设计思路如下: 当
    发表于 12-12 07:07

    RTOS Crash 问题全维度分析与解决指南

    rt_sem_release后Crash(实际误调用rt_sem_take); 原理 :RTOS中断上下文不允许调用阻塞API(无任务切换上下文); 解决 : 中断仅调用“中断安全版
    发表于 12-08 03:56

    FreeRTOS 空闲任务

    几乎所有的小型 RTOS 中都会有一个空闲任务,空闲任务属于系统任务,是必须要执行的,用户程序不能将其关闭。不光小型系统中有空闲任务,大型的
    发表于 12-04 07:35

    学习RTOS的意义?

    RTOS实现多任务管理。 嵌入式操作系统有众多的软件组件,可以极大的加速项目进度,避免重复造车轮。 2.技能需要 掌握操作系统,和基于RTOS的编程,实现更好的职业规划,对个人发展是必不可少的。 在招聘网
    发表于 11-27 08:16

    RTOS 必学概念:任务、信号量、队列一次搞懂

    如果你刚接触RTOS(实时操作系统),很可能会有这样的困惑:“RTOS和裸机程序到底有什么区别?”“任务是线程吗?为什么要分任务?”“信号量和互斥锁有什么区别,不都是同步手段吗?”“队
    的头像 发表于 11-17 10:53 690次阅读
    <b class='flag-5'>RTOS</b> 必学概念:<b class='flag-5'>任务</b>、信号量、队列一次搞懂

    嵌入式rtos哪一个更加值得去学习?

    嵌入式圈里聊 RTOS,总有人揪着任务调度的那点差异争得面红耳赤,可实际上这东西做透了大家都大差不差 —— 优先级调度、时间片轮转,核心逻辑翻来覆去就那些,真到项目里谁也没比谁快出多少,哪怕是所谓
    的头像 发表于 11-05 10:48 889次阅读
    嵌入式<b class='flag-5'>rtos</b><b class='flag-5'>中</b>哪一个更加值得去学习?

    py32f030移植thread nano开启读保护,任务切换失败的原因?

    读option,并打印;同时在切换任务之前,打印切换任务指针,都是一样的。不知道问题出在哪
    发表于 09-16 06:39

    py32f030 移植thread nano 开启读保护,任务切换失败怎么解决?

    读option,并打印;同时在切换任务之前,打印切换任务指针,都是一样的。不知道问题出在哪
    发表于 08-29 07:10

    【RA4L1-SENSOR】05 按键实现RTOS任务切换

    与计数功能的切换,为之后的多任务切换做个铺垫。 2. 软件部分 将上次的实验工程复制一份,重命名为05_Button_Switch_Task 2.1 绑定按键IO &&
    发表于 06-16 22:38