为了了解实时操作系统 (RTOS) 的功能,需要了解通用机制和 Linux 特定机制。
当前正在运行的低优先级任务必须被抢占以允许实时关键的任务运行。抢占依赖任务的调度策略。实时系统另一个重要的方面是确保实时任务对某一些资源的独占。
实时系统是运行 RTOS 和至少一个实时任务的平台。RT 任务是必须在特定截止日期之前完成的任务。这些任务可以是定期的,也可以是非周期性的,要确保根据执行频率和截止日期的严格程度来安排它们。系统上也可能运行非实时任务。
主线 Linux 内核为不同的应用领域 (如服务器或台式 PC) 实现了三种不同的抢占模型。有了 PREEMPT_RT 补丁,还有两个额外的抢占模型可用。『Fully Preemptible Kernel』模型是将 Linux 变成 RTOS 的模型。
各种抢占模型是特定于内核的。原则上,用户空间进程始终是抢占式的。 正在运行的任务的抢占由调度进程执行。此操作可以由内核交互 (如系统调用) 或异步事件 (如中断) 触发。调度进程保存抢占任务的上下文,并还原新任务的上下文。 Linux 内核实现了多个抢占模型。在构建内核时选择所需的模型。必须选择『Fully Preemptible Kernel』抢占模型才能将 Linux 作为 RTOS。为了完整起见,现有 Linux 抢占模型的列表和简短说明如下。最后两个条目仅 PREEMPT_RT 补丁打上后才能够启用。
当具有高优先级的任务由于资源互斥而被优先级较低的任务阻止时,优先级介于其他任务之间的第三个任务可以在优先级最高的任务恢复之前运行并完成。这种现象称为优先级倒置。可以通过优先继承来解决。
优先级继承是解决优先级倒置问题的一种方法。
优先级反转问题通过优先级继承解决:
这意味着当 H 需要 L 持有的资源时,L 继承了 H 的优先级 (5),以便更快地释放资源 (6)。当 M 准备好运行时,M 必须等到当前优先级较高的任务 L 释放资源并且 H 完成运行 (7)。
Linux 内核实现了多个实时和非实时调度策略。根据任务的计划策略,调度进程决定交换哪个任务以及接下来处理哪个任务。
根据所选的任务策略和关联的规则,调度进程决定交换哪个任务以及接下来处理哪个任务。Linux 内核实现了多个调度策略。它们分为非实时策略和实时策略。调度策略已在主线 Linux 中实现。
非实时策略:
实时策略:
RT 限制机制可防止系统在实时应用进程中出现运行时程序失败时挂起。这种机制使得停止此类应用进程成为可能。RT 限制的设置将导出到 proc 文档系统中。
实时应用进程中的运行失败可能导致整个系统挂起。这样的失败可能类似于对『while (true) {}』循环的调用。当实时应用进程具有尽可能高的优先级并使用 SCHED_FIFO 策略进行计划时,任何其他任务都无法抢占它。这会导致系统阻止所有其他任务,并以 100% 的 CPU 负载调度此循环。实时限制是一种通过限制每个周期的实时任务执行时间来避免这种情况的机制。这些设置将导出到 proc 文档系统中。默认设置为:
# cat /proc/sys/kernel/sched_rt_period_us
1000000
# cat /proc/sys/kernel/sched_rt_runtime_us
950000
要达到实时任务和更大时间段的 CPU 使用率仅为 50%,可以使用以下命令更改这些值:
# echo 2000000 > /proc/sys/kernel/sched_rt_period_us
# echo 1000000 > /proc/sys/kernel/sched_rt_runtime_us
如果实时任务运行时的长度与时间段相同,则禁用实时限制。这是通过将『-1』写入『sched_rt_runtime_us』自动完成的:
# echo -1 > /proc/sys/kernel/sched_rt_runtime_us
这种机制已经在主线 Linux 中实现。
低延迟是实时计算环境中的一项关键要求,因为它可以确保任务或流程能够快速、可预测地响应外部事件或输入。
当实时系统被说成有延迟或有需要调试的延迟时,术语延迟是指『任务或操作需要很长时间才能完成的情况』。在实时上下文中,系统执行特定任务所需的时间 (即任务的延迟) 很重要,因为每个任务都必须能够在指定的截止日期之前完成。
如果一个 RT 任务没有在规定的时间限制内完成,那就和任务根本没完成一样糟糕。这就是为什幺开发人员花费大量时间确保即使在最坏的情况下,任务仍然可以在截止日期之前完成。这意味着,在评估实时系统的性能时,要测量的最重要的延迟值是最大延迟。
Dynticks 或动态 ticks 或无 HZ 模式可减少定时器中断开销。
在很长一段时间里,Linux 内核都有一个周期性的中断,这使得内核调度进程来平衡和调度在 CPU 之间运行的线程。此中断称为定时器 tick,它以固定速率在每个 CPU 或内核上生成 100-1000 HZ。无论 CPU 的电源状态如何,内核都会为此中断提供服务。此模式由选项 CONFIG_HZ_PERIODIC 启用。
CONFIG_NO_HZ_IDLE 模式允许 CPU 在空闲时不受干扰,并且可以节省电量,因为它只是在需要服务定时器时唤醒 CPU.
全 dynticks 系统 (无滴答) 模式由 CONFIG_NO_HZ_FULL 启用,并由引导参数激活 nohz_full。内核会尽可能自适应地尝试关闭 tick,即使 CPU 正在运行具有函数 tick_nohz_full_cpu 的任务。