我正在考虑将我的产品从 RTOS 转移到嵌入式 Linux。我没有太多的实时要求,我有的几个 RT 要求大约是 10 毫秒。
有人能指点我一个参考资料,告诉我当前版本的 Linux 是如何实时的吗?
从商业 RTOS 迁移到 Linux 是否还有其他问题?
您可以从 Real Time Linux wiki和FAQ中获得大部分答案
库存 2.6 linux 内核的实时功能是什么?
传统上,Linux 内核只允许一个进程在某些情况下抢占另一个进程:
- 当 CPU 运行用户模式代码时
- 当内核代码从系统调用或中断返回用户空间时
- 当内核代码代码块在互斥体上或显式将控制权让给另一个进程时
如果内核代码在发生需要高优先级线程开始执行的某些事件时执行,则高优先级线程不能抢占正在运行的内核代码,直到内核代码显式让出控制权。在最坏的情况下,延迟可能会达到数百毫秒或更长。
Linux 2.6 配置选项 CONFIG_PREEMPT_VOLUNTARY 引入了对长延迟最常见原因的检查,以便内核可以自愿将控制权交给等待执行的更高优先级任务。这可能会有所帮助,但是虽然它减少了长延迟的发生(数百毫秒到可能的秒或更长时间),但它并没有消除它们。然而,与 CONFIG_PREEMPT(下文讨论)不同,CONFIG_PREEMPT_VOLUNTARY 对系统整体吞吐量的影响要小得多。(与往常一样,吞吐量(系统的整体效率)和延迟之间存在经典的权衡。现代系统的 CPU 速度更快,通常需要权衡吞吐量以降低延迟,
2.6 Linux 内核有一个额外的配置选项 CONFIG_PREEMPT,它使自旋锁保护区域和中断处理程序之外的所有内核代码都有资格被更高优先级的内核线程进行非自愿抢占。使用此选项,最坏情况下的延迟降至(大约)个位数毫秒,尽管某些设备驱动程序可能具有中断处理程序,这将引入比这更糟糕的延迟。如果实时 Linux 应用程序需要小于个位数毫秒的延迟,强烈建议使用 CONFIG_PREEMPT_RT 补丁。
正如您在常见问题解答中所说的那样,他们还有一个“陷阱”列表。
编写实时应用程序时要记住哪些重要事项?
在初始启动阶段注意以下事项:
- 尽快从 main() 调用 mlockall()。
- 在应用程序启动时创建所有线程,并触摸每个线程的整个堆栈的每个页面。切勿在 RT 显示期间动态启动线程,这将破坏 RT 行为。
- 切勿使用已知会产生页面错误的系统调用,例如 fopen()。(打开文件执行 mmap() 系统调用,这会生成页面错误)。
- 如果您使用“编译时全局变量”和/或“编译时全局数组”,则使用 mlockall() 来防止访问它们时出现页面错误。
更多信息:HOWTO:构建 RT 应用程序
他们还有一个您可能想要结帐的大型出版物页面。
你看过Xenomai吗?它可以让您在 Linux 之上运行“硬实时”进程,同时仍然允许您访问常规 Linux API 来满足所有非实时需求。
使用 Linux 实现实时功能有两种根本不同的方法。
使用诸如 rt-preempt 补丁之类的东西修补现有内核。这最终将导致完全抢占式内核
双内核方法(如 xenomai、RTLinux、RTAI...)
从 RTOS 转移到 Linux 有很多陷阱。
也许你真的不需要实时?
我在培训课程中谈论的是实时 Linux:
答案可能是“足够好”。
如果您运行的是嵌入式系统,您可能可以控制盒子上的所有或大部分软件。
Stock Linux 2.6 有几个适合低延迟任务的特性——主要是:
假设您使用的是单核机器,如果您只有一个任务将其调度策略设置为 SCHED_FIFO 或 SCHED_RR(如果您只有一个任务则无关紧要),并使用 mlockall 锁定其所有内存(),然后它将在准备好运行时立即安排。
那么您唯一需要担心的是内核的某些不可抢占部分的完成时间超过了您可接受的延迟时间 - 这在嵌入式系统中不太可能发生,除非发生一些不好的事情,例如极端的内存压力,或者你的司机很狡猾。
我想“试试看”是一个很好的答案,但在你的情况下这可能相当复杂(并且可能涉及编写设备驱动程序等)。
查看 sched_setscheduler 的文档以获取一些有用的信息。