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

    文章

    5305

    浏览量

    119903
  • RTOS
    +关注

    关注

    21

    文章

    809

    浏览量

    119383
  • 电池
    +关注

    关注

    84

    文章

    10425

    浏览量

    128768
收藏 人收藏

    评论

    相关推荐

    freertos和rtos区别是什么

    (Real-Time Operating System,实时操作系统)是一种特殊的操作系统,它能够为实时任务提供确定性的响应时间。RTOS 通常用于嵌入式系统,如工业自动化、汽车电子、医疗设备等领域
    的头像 发表于 09-02 14:18 876次阅读

    简单认识RTOS实时操作系统

    RTOS(Real Time Operating System,实时操作系统)是一种专门设计用于在严格时间限制内处理任务的操作系统。它以其高实时性、多任务处理能力和资源管理能力在工业自动化、医疗设备、航空航天、汽车电子等众多领域
    的头像 发表于 08-20 11:20 2291次阅读

    什么是实时操作系统(3)-在 RTOS 可以期待什么?

    RTOS使用各种机制来管理任务、事件和内存,以确保嵌入式系统满足时间约束。在本节,您将了解构建嵌入式应用程序时需要考虑的RTOS功能,例如确定性、空间和时间分离、调度、内存管理和进程
    的头像 发表于 07-23 12:00 964次阅读
    什么是实时操作系统(3)-在 <b class='flag-5'>RTOS</b> <b class='flag-5'>中</b>可以期待什么?

    RTOS SDK的socket怎么正确使用?

    我按照《ESP8266 RTOS SDK 编程⼿册 Version 1.3.0》 “3. 网络⽰例: TCP server” 建立TCP server,但是编译无法识别结构体 struct
    发表于 07-22 07:05

    编写一个任务调度程序,在上下文切换后遇到了一些问题求解

    \"rfe\" 不会在 A[11] 寄存器设置新的返回地址。 当任务函数以\"ret16\" 结束时,µC 将在陷阱运行。 我在上下文切换的准备过程
    发表于 05-22 07:50

    请问CMSIS-RTOS RTX的任务调度锁在哪里?

    请问一下,CMSIS-RTOS RTX的任务调度锁在哪里?谢谢!
    发表于 05-13 08:28

    freeRTos任务切换的耗时是多少?

    有没有人测量过free R Tos任务切换, 二值信号切换,定时器切换 耗费的时间 或者是 时钟周期大概是多少?
    发表于 04-28 06:47

    求助,是否可以不用pendSV中断做任务切换

    freeRTOS的任务切换我的理解是:通过SysTick中断去触发pendSV中断去做任务切换,因为pendSV中断优先级最低,所以任务
    发表于 04-16 07:59

    基于RTOS的应用进程的典型线程

    RTOS的关键因素是最小的中断延迟和最小的线程切换延迟。RTOS的价值在于它的响应速度或可预测性,而不是它在给定时间段内可以执行的工作量。
    发表于 03-05 09:32 513次阅读
    基于<b class='flag-5'>RTOS</b>的应用进程<b class='flag-5'>中</b>的典型线程

    分享几点RTOS相比裸机的优势

    嵌入式系统,有很多方式实现任务调度。功能有限的小系统,无限循环足够实现小系统的功能。当软件设计变得庞大且复杂时,开发者应该考虑使用实时操作系统RTOS
    的头像 发表于 01-24 18:23 1533次阅读
    分享几点<b class='flag-5'>RTOS</b>相比裸机的优势

    无法在AURIX™ Development Studio调试freeRTOS任务怎么解决?

    我们正在开发 AURIX™ TriCore™ TC389 控制器。 你能否建议需要使用哪个 RTOS 以及首选 IDE调试器来进行开发过程? 此外,我无法在 AURIX™ Development Studio 调试 freeRTOS
    发表于 01-18 07:41

    如何设定RTOS任务栈(线程栈)大小呢?

    首先说明的是,在 `RT-Thread` ,将本文提及的 `任务` 称之为 `线程`。
    的头像 发表于 12-01 16:40 1637次阅读

    RTOS内功修炼记(一)— 任务到底应该怎么写?

    本篇文章讲述了任务的三大元素:任务控制块、任务栈、任务入口函数,并讲述了编写RTOS任务入口函数
    的头像 发表于 12-01 16:36 701次阅读
    <b class='flag-5'>RTOS</b>内功修炼记(一)— <b class='flag-5'>任务</b>到底应该怎么写?

    FreeRTOS系列技术文章:上下文切换

    嵌入式实时操作系统(RTOS的上下文切换是指保存和恢复任务的状态,以使调度程序能够切换到另一个任务
    的头像 发表于 11-21 15:48 1095次阅读

    新手必看的RTOS基础知识

    时间片调度保证每个线程都有一个要执行的槽。这种类型的调度通常不利于实时应用。如果需要,TI-RTOS内核支持使用任务进行时间切片调度。
    的头像 发表于 11-20 16:06 2328次阅读
    新手必看的<b class='flag-5'>RTOS</b>基础知识