为什么 RTOS 任务必须无限循环执行?
Why do RTOS tasks have to be executed in infinite loop?
嗨,我是 RTOS 的新手,在我阅读的几乎所有文档中,它都表明任务必须处于无限循环中,但 none 说明了原因。谁能帮忙解释一下?谢谢
在随任何 GPOS(通用操作系统)一起提供的正常 C 语言实现中,例如 Linux、Windows、Mac OSX,C 运行time 库负责启动任务(在 GPOS 上下文中可以称为 thread/process),并在任务结束时充当收集器。
意思是,crt(C运行time)会调用main()
的任务来启动它,当任务returns用return
语句时,控制传回 OS.
的 crt
在RTOS中,虽然可以用C语言编程,但是没有crt本身的具体实现。 "Startup" 函数(通常用汇编语言编写)调用 main。但是,此启动代码没有任何机制来收集任务的 return 值,因此任务需要在无限循环中 运行 以将控制权保持在任务本身内。否则,CPU/MCU 将没有任何 return 地址可去。
但是,可以使用 RTOS 提供的任务管理 API 来结束任务。在这种情况下,控件将转到从 RTOS.
调用 task_kill()
(代表性)API 的代码
我认为 "an RTOS task must be an infinite loop" 的说法并不完全准确。我认为更正确的说法是"for many RTOS, a task must not return"。原因是最初调用任务的 RTOS 调度程序并非设计用于处理来自任务的 return。如果任务执行 return,则 RTOS 调度程序可能会断言错误。
我可以猜出许多 RTOS 调度程序不处理来自任务的 return 的几个原因。首先,无限循环是嵌入式系统中最典型的任务类型。结束的任务不太常见。其次,RTOS 调度程序可能必须更复杂才能处理 returning 任务。第三,RTOS 设计者可能不想假设任务 returns 时应该做什么,而是他们希望任务设计者显式调用适当的任务终止例程。
对于许多不允许任务 return 的 RTOS,无限循环并不是唯一的解决方案。 RTOS 可以提供一个任务终止例程,从任务列表中删除任务,这样它就不会再被调度。如果一个任务调用任务终止例程,那么该任务不必是一个无限循环,它也不会 return 给它的调用者。 (即,RTOS 任务终止例程不 return 因此调用它的任务也不 return。)例如,FreeRTOS 有 vTaskDelete() 和 uC/OS-II 有 OSTaskDel()删除不是无限循环的任务。
无限循环是嵌入式系统中的一种常见任务类型,因为许多嵌入式系统只是一遍又一遍地做同样的事情。许多嵌入式系统与 PC 不同,因为它们没有用户与之交互、启动和终止各种任务或应用程序。
它们不会,但如果任务功能 运行s 完成,任务将终止。
您或许可以选择在每次需要时实例化一个新的运行-to-completion任务,但是实例化一个任务很耗时而且可能不确定性的,因此不适合硬实时响应。让任务等待某个阻塞对象(例如事件、信号量或计时器)会更高效且响应更快,这样它就可以在每次需要时做出确定性的响应。另一方面,如果你有许多不同的非实时任务,偶尔只需要 运行,运行-to-completion 模式可以节省资源。
至少有一项任务需要 运行 无限期地进行,但是 - 如果一切都停止了,您的系统将什么都不做,直到电源循环或复位断言(例如通过看门狗定时器)。
RTOS 实现各不相同,您需要检查您的 RTOS 如何处理终止线程函数。您可能需要显式终止调用以确保内核释放资源。
如果您的系统需要某种形式的受控正常关闭,则无需将任务编码为无限循环,而是让循环有条件地退出,以便任务可以根据请求终止,例如;
while( (event_flags & TERMINATE) == 0 )
{
event_flags = eventWait( WAIT_FOREVER ) ;
// handle events
...
}
嗨,我是 RTOS 的新手,在我阅读的几乎所有文档中,它都表明任务必须处于无限循环中,但 none 说明了原因。谁能帮忙解释一下?谢谢
在随任何 GPOS(通用操作系统)一起提供的正常 C 语言实现中,例如 Linux、Windows、Mac OSX,C 运行time 库负责启动任务(在 GPOS 上下文中可以称为 thread/process),并在任务结束时充当收集器。
意思是,crt(C运行time)会调用main()
的任务来启动它,当任务returns用return
语句时,控制传回 OS.
在RTOS中,虽然可以用C语言编程,但是没有crt本身的具体实现。 "Startup" 函数(通常用汇编语言编写)调用 main。但是,此启动代码没有任何机制来收集任务的 return 值,因此任务需要在无限循环中 运行 以将控制权保持在任务本身内。否则,CPU/MCU 将没有任何 return 地址可去。
但是,可以使用 RTOS 提供的任务管理 API 来结束任务。在这种情况下,控件将转到从 RTOS.
调用task_kill()
(代表性)API 的代码
我认为 "an RTOS task must be an infinite loop" 的说法并不完全准确。我认为更正确的说法是"for many RTOS, a task must not return"。原因是最初调用任务的 RTOS 调度程序并非设计用于处理来自任务的 return。如果任务执行 return,则 RTOS 调度程序可能会断言错误。
我可以猜出许多 RTOS 调度程序不处理来自任务的 return 的几个原因。首先,无限循环是嵌入式系统中最典型的任务类型。结束的任务不太常见。其次,RTOS 调度程序可能必须更复杂才能处理 returning 任务。第三,RTOS 设计者可能不想假设任务 returns 时应该做什么,而是他们希望任务设计者显式调用适当的任务终止例程。
对于许多不允许任务 return 的 RTOS,无限循环并不是唯一的解决方案。 RTOS 可以提供一个任务终止例程,从任务列表中删除任务,这样它就不会再被调度。如果一个任务调用任务终止例程,那么该任务不必是一个无限循环,它也不会 return 给它的调用者。 (即,RTOS 任务终止例程不 return 因此调用它的任务也不 return。)例如,FreeRTOS 有 vTaskDelete() 和 uC/OS-II 有 OSTaskDel()删除不是无限循环的任务。
无限循环是嵌入式系统中的一种常见任务类型,因为许多嵌入式系统只是一遍又一遍地做同样的事情。许多嵌入式系统与 PC 不同,因为它们没有用户与之交互、启动和终止各种任务或应用程序。
它们不会,但如果任务功能 运行s 完成,任务将终止。
您或许可以选择在每次需要时实例化一个新的运行-to-completion任务,但是实例化一个任务很耗时而且可能不确定性的,因此不适合硬实时响应。让任务等待某个阻塞对象(例如事件、信号量或计时器)会更高效且响应更快,这样它就可以在每次需要时做出确定性的响应。另一方面,如果你有许多不同的非实时任务,偶尔只需要 运行,运行-to-completion 模式可以节省资源。
至少有一项任务需要 运行 无限期地进行,但是 - 如果一切都停止了,您的系统将什么都不做,直到电源循环或复位断言(例如通过看门狗定时器)。
RTOS 实现各不相同,您需要检查您的 RTOS 如何处理终止线程函数。您可能需要显式终止调用以确保内核释放资源。
如果您的系统需要某种形式的受控正常关闭,则无需将任务编码为无限循环,而是让循环有条件地退出,以便任务可以根据请求终止,例如;
while( (event_flags & TERMINATE) == 0 )
{
event_flags = eventWait( WAIT_FOREVER ) ;
// handle events
...
}