icon
password
new update day
URL
type
Post
status
Published
slug
2025/02/22/Some-configuration-suggestions-to-improve-the-real-time-performance-of-xenomai-/PREEMPT-RT
summary
提供了一些配置建议以提高xenomai/PREEMPT-RT的实时性能,涵盖了实时系统的定义、分类、影响因素及优化措施,包括硬件、BIOS设置、内核参数和软件优化等方面,以确保系统在规定时间内响应外部事件。
tags
Linux
rt-kernel
category
Linux
Created_time
Feb 22, 2025 07:50 AM
created days
Last edited time
Feb 22, 2025 08:39 AM

【转载】有利于提高xenomai /PREEMPT-RT 实时性的一些配置建议

notion image
xenomai /PREEMPT-RT 实时性优化指南
本文讲述一些有利于提高xenomai实时性的配置建议,部分针对X86架构,但它们的底层原理相通,同样适用于其他CPU架构和系统,希望对你有用。

一、前言

1. 什么是实时

“实时”一词在许多应用领域中被广泛使用,但人们对它的理解往往存在偏差。常见的误解是,只要一个系统能够快速响应外部事件,就被认为是实时系统。这种解释将“实时”等同于“快速”,然而,“快速”是一个相对概念,并未准确反映实时系统的核心特性。
为了更准确地理解“实时”,我们可以从自然界中的生物行为中寻找启示。生物在其栖息地中的实时行为并不取决于它们的绝对速度。例如,乌龟和猫都能有效地响应来自环境的外部刺激。尽管乌龟的反应速度远慢于猫,但它处理事件的能力与其动作的协调性相匹配,这是生物在环境中生存的基本条件。
相反,如果环境中的事件速度超出了生物的处理能力,其行为将失效,生存也会受到威胁。例如,苍蝇可能被苍蝇拍捕捉,老鼠可能落入陷阱,猫可能被高速行驶的汽车撞到。这些例子中,苍蝇拍、陷阱和汽车代表了超出生物实时能力范围的异常事件,可能导致严重后果。
notion image
以上例子表明,实时性并不单纯意味着“快”,而是与系统运行的环境密切相关。
实时系统是指必须在设定的截止时间内对环境中的事件做出响应的系统,否则可能导致严重后果。
notion image
再以船舶的制导系统为例,尽管它的响应速度较慢,通常有几分钟的时间来做出控制决策,但根据我们的定义,它仍然是一个实时系统。这是因为如果系统未能在规定时间内完成响应,可能会导致严重的后果。

2. 实时分类

根据错过截止时间可能产生的后果,实时任务可以分为以下三类:

硬实时(Hard real time system)

如果任务未能在截止时间内完成,可能对受控系统造成灾难性后果,则该任务属于硬实时任务。
硬实时任务通常出现在安全关键系统中,涉及传感、驱动和控制活动。例如:
  • 汽车安全气囊的检测与控制:必须在碰撞发生的瞬间完成检测并触发安全气囊,否则可能导致严重的人身伤害。
  • 反导弹系统:反导弹系统由一系列硬实时任务组成,包括探测来袭导弹、定位反导炮以及在导弹到达前将其摧毁。任何一个任务失败都会导致拦截失败,造成灾难性后果。

强实时(Firm real time system)

如果任务未能在截止时间内完成,其结果对系统无用,但不会造成任何损害,则该任务属于强实时任务。
强实时任务常见于网络应用程序和多媒体系统中找到,这些系统更注重数据的时效性而非延迟处理。例如:
  • 视频播放:如果某一帧未能按时解码并显示,系统会直接丢弃该帧,继续播放下一帧。
  • 音/视频编解码:如果未能在设定的码率时序范围内完成处理,生成的结果将被丢弃,系统会继续处理下一组数据。
  • 在线图像处理:实时图像处理任务要求在规定时间内完成,否则结果将被忽略。

软实时(Soft real time system)

如果任务未能在截止时间内完成,其结果仍然对系统有用,尽管可能导致性能下降,则该任务属于软实时任务。
软实时任务通常与系统-用户交互相关,轻微的延迟不会对系统功能造成严重影响,但可能影响用户体验。例如:
  • 用户界面的命令解释器:用户输入命令后,系统稍作延迟响应并不会导致功能失效。
  • 处理来自键盘的输入数据:输入数据的处理稍有延迟,用户可能感知到但不影响整体功能。
  • 在屏幕上显示消息:消息显示的延迟可能会让用户感到不便,但不会影响系统的核心功能。
  • 网页浏览:页面加载稍有延迟,用户可能会感到体验不佳,但不会影响浏览功能。

3.常见的RTOS

小型实时操作系统 UCOS、FreeRTOS、RT-Thread…
大型实时操作系统 RT linux、VxWorks、QNX、sylixOS…
notion image

4. latency 和 jitter

硬实时系统必须在设定的截止时间内对环境中的事件做出响应。因此,硬实时操作系统最重要的特性之一是确定性和可预期性
操作系统的实时性能通常通过 Latency(延迟) 和 Jitter(抖动) 来衡量:
  • Latency(延迟):指事件预期发生时间与实际发生时间之间的时间差。
  • Jitter(抖动):指事件实际发生的最大时间与最小时间之间的差值。
根据实时性的定义,延迟必须是确定的,且不能超过截止时间(Deadline),否则可能导致严重后果。
notion image
在评估硬件和实时系统是否适用于特定实时应用场景时,通常可以简化为对以下两个方面的考量:
  1. 实时性能:系统是否能够满足延迟和抖动的要求。
  1. 硬件资源:硬件性能是否足以支持实时任务的执行。
在决定是否采用某个实时系统时,需要结合具体应用场景进行评估。如果系统无法满足实时性要求,则需要考虑对现有系统进行优化或更换方案。

二、实时性的影响因素

硬实时操作系统最重要的特性之一是确定性和可预测性,系统必须保证满足所有关键时序约束。然而,实时性受多种因素影响,包括硬件架构特征、内核机制与策略、编程语言以及软件设计等。
​根据实时性定义,计算机系统中所有导致程序执行时间不确定的因素,都是实时性的影响因素。​

1. 硬件

CPU架构

硬件方面,处理器的内部特性是影响调度可预测性的首要因素。例如,指令预取、流水线操作、分支预测、高速缓存(Cache)和直接存储器访问(DMA)机制等特性虽然提升了处理器的平均性能,但也引入了不确定性,导致难以精确估计最坏情况执行时间(WCET, Worst-case Execution Time)。
高端 CPU(如 i5、i7)的实时性不一定优于低端 CPU(如赛扬、Atom)。高端 CPU 的设计目标是高吞吐量,而非实时性,实时性与吞吐量往往不可兼得。

Cache

  • L1/L2 Cache:访问延迟仅为内存的 1/15 到 1/100。为了追求极限性能,应尽量减少 Cache Miss,确保实时任务尽可能从 Cache 中获取数据。为优化实时性,可以为实时任务分配专用的 CPU 核心,以充分利用非共享的 L1/L2 Cache。
  • L3 Cache:多个 CPU 核心和 GPU 共享 L3 Cache,无法避免非实时任务或 GUI 任务对实时任务的干扰。

X86平台优化

Intel 推出了资源调配技术(Intel RDT),提供监控和分配能力,包括:
  • 缓存分配技术(Cache Allocation Technology, CAT):允许用户为每个核心分配特定的 L3 Cache 容量,提升实时任务的 Cache 命中率,减少延迟和抖动。
    • CAT(缓存分配技术,Cache Alocation Technology),对最后一级缓存(L3 Cache)实现分区,用户可以通过限制每个核心能够向其中分配缓存行的LLC数量,将LLC的部分分配给特定核心,使用该技术可以提升实时任务Cahe命中率,减少MSI延迟和抖动,进而提升实时性能。(不是所有intel处理器具有该功能,一开始只有服务器CPU提供该支持,据笔者了解,6代以后的CPU基本支持CAT。关于CAT 见github),对于大多数Linux发行版,可直接安装使用该工具,具体的cache分配策略可根据后面的资源隔离情况进行。
      • sudo apt-get install intel-cmt-cat
  • 代码和数据优先级(Code and Data Prioritization, CDP):优化代码和数据访问优先级。
  • 内存带宽分配(Memory Bandwidth Allocation, MBA):控制内存带宽分配。
RDT 最初用于解决云计算中的“Noisy Neighbor”问题,即某个虚拟机过度消耗 Cache 或内存带宽,影响其他虚拟机的性能。类似地,在实时系统中,非实时任务过度消耗 L3 Cache 或内存带宽会严重影响实时任务的性能。RDT 技术通过精细化的资源控制,显著提升了实时性能。
同样对于我们的实时系统也是类似:由于L3 Cache多核共享,如果有一个过度消耗cache的非实时应用耗尽了L3缓存或者大量的内存带宽,将无法保障xenomai实时应用的性能。
以往虚拟化环境中解决方法是通过控制虚拟机逻辑资源(cgroup)但是调整粒度太粗,并且无法控制处理器缓存这样敏感而且稀缺的资源。为此Intel推出了RDT技术。在Intel中文网站的 通过英特尔® 资源调配技术优化资源利用视频形象介绍了RDT的作用。
Intel的Fenghua Yu在Linux Foundation上的演讲 Resource Allocation in Intel® Resource Director Technology 可以帮助我们快速了解这项技术。
总的来说,RDT让我们实现了控制处理器缓存这样敏感而且稀缺的资源,对我们对实时性能提升有很大帮助(不仅限于xenomai,RTAI、PREEMPT-RT均适用)。

ARM64平台优化

以瑞芯微 RK35xx 平台为例,可通过以下方式优化实时性:
  • Cache 分区:ARM Cortex-A55 支持将 L3 Cache 划分为多个区域,并为每个 CPU 核心分配独占的 Cache 区域。
  • 核心隔离:通过内核参数(如 isolcpus 和 nohz_full)隔离特定核心,确保实时任务独占资源。
a) cache 分片
ARM Cortex-A55 架构支持对 L3 Cache 空间进行划分。具体原理是:Cortex-A55 的 L3 Cache 空间被划分为 4 个区域(P0、P1、P2、P3),每个 CPU 核心可以配置使用其中的一个或多个区域。配置通过修改 rkbin​ 中的 RKBOOT/RK3568MINIALL.ini​ 文件实现,例如:
[BOOT1_PARAM] WORD_3=0xc33
​WORD_3​ 的值 0xc333​ 表示:
  • cpu0、cpu1、cpu2 共享 L3 的 P0、P1 区域。
  • cpu3 独占 L3 的 P2、P3 区域。
​WORD_3​ 的配置值详细说明如下:
  • bit0~bit3:分配给 cpu0 的 4 个 L3 区域的掩码。例如,bit0 为 1 表示 L3 的第一块区域分配给 cpu0,bit1 为 1 表示第二块区域分配给 cpu0,以此类推。
  • bit4~bit7:分配给 cpu1 的 4 个 L3 区域的掩码。
  • bit8~bit11:分配给 cpu2 的 4 个 L3 区域的掩码。
  • bit12~bit15:分配给 cpu3 的 4 个 L3 区域的掩码。
配置后可以通过下面开机LOG确认
INFO: L3 cache partition cfg-c333
此配置表示 cpu3 独占 256KB 的 L3 Cache 空间。
b)隔离核心
在 bootargs 中添加 isolcpus=3 nohz_full=3,可以将 cpu3 从系统任务调度中隔离出来,使其专门用于实时任务。关于内核参数的详细说明,请参见后文。

TLB

与 Cache 类似,TLB(Translation Lookaside Buffer)的访问延迟也会影响实时性。。

分支预测

现代 CPU 的流水线级数非常长,一般都在10级以上,指令分支判断错误(Branch Mispredict)的时间代价昂贵。如果判断预测正确,可能只需要一个时钟周期;如果判断错误,就还是需要10-20 左右个时钟周期来重新提取指令。
如下为对同一随机组数,排序与未排序情况下for循环测试:
notion image
数据有规律和无规律两种情况下同一段代码执行时间相差巨大。
现代 CPU 的分支预测正确率已经可以在一般情况下维持在 95% 以上,所以当分支存在可预测的规律的时候,还是以性能测试的结果为最终的优化依据。

Hyper-Threading

人们对CPU的性能的追求是无止境的,在CPU性能不断优化提高过程中,对于单一流水线,最佳情况下,IPC 也只能到 1。无论做了哪些流水线层面的优化,即使做到了指令执行层面的乱序执行,CPU 仍然只能在一个时钟周期里面取一条指令。
为使IPC>1,诞生了多发射(Mulitple Issue)和超标量(Superscalar)技术,伴随的是每个CPU流水线上各种运算单元的增加。但是当处理器在运行一个线程,执行指令代码时,一方面很多时候处理器并不会使用到全部的计算能力,另一方面由于CPU在代码层面运行前后依赖关系的指令,会遇到各种冒险问题,这样CPU部分计算能力就会处于空闲状态。
为了进一步“压榨”处理器,那就找没有依赖关系的指令来运行好,即另一个程序。一个核可以分成几个逻辑核,来执行多个控制流程,这样可以进一步提高并行程度,这一技术就叫超线程,又称同时多线程(Simultaneous Multi-Threading,简称 SMT)。
由于超线程技术通过双份的 PC 寄存器、指令寄存器、条件码寄存器,在逻辑层面伪装为2个CPU,但指令译码器和ALU是公用的,这就造成实时任务运行时在CPU执行层面的不确定性,造成非实时线程与实时线程在同一物理核上对CPU执行单元的竞争,影响实时任务实时性。

电源管理与调频

我们知道CPU场效应晶体管FET构成,其简单示意图如下。
notion image
当输入高低电平时,CL被充放电,假设充放电a焦耳的能量。因为CL很小,这个a也十分的小,几乎可以忽略不计。为了提高CPU性能,不断提高处理器的时钟频率,但如果我们以1GHz频率翻转这个FET,则能量消耗就是a × 10^9,这就不能忽略了,再加上CPU中有几十亿个FET,消耗的能量变得相当可观。
详细的参考:https://zhuanlan.zhihu.com/p/56864499
为了省电,操作系统会随着工作量不同,动态调节CPU频率和电压。但是调频会导致CPU停顿(CPU停顿时间10us~500us不等),运行速度降低导致延迟增加,严重影响实时性能。
除了调频以外,另一个严重影响实时性的是,系统进入更深层次的省电睡眠状态,这时的唤醒延迟长达几十毫秒。
动态调频和深度睡眠模式会显著增加延迟:
  • 调频:CPU 频率调整可能导致停顿(10us~500us),增加延迟。
  • 深度睡眠:唤醒延迟可能长达几十毫秒,严重影响实时性。

Multi-Core

接收 IRQ 的 CPU 可能不是响应者休眠所在的 CPU,在这种情况下,前者必须向后者发送重新调度请求,以便它恢复响应者。这通常是通过处理器间中断完成的,也就是IPI,IPI的发送和处理进一步增加了延迟。
中断周期及测试时长
最小
平均
最大
100us 21h
0.086us
0.184us
4.288us
此外,多核总线共享、LLC共享,NUMA架构远端内存访问等,均会导致访问延迟不确定。

DMA

DMA突发传输不确定占用总线带宽,影响程序执行;总线动态调频省电等

other

  • DMA传输不确定性
  • 其他影响因素有​内存、散热​。
提升内存频率可降低内存访问延时;使用双通道内存,这两个内存CPU可分别寻址、读取数据,从而使内存的带宽增加一倍,数据存取速度也相应增加一倍(理论上),内存访问延时得到缩短,进而提升系统的实时性能;
处理器散热设计不好,温度过高时会引发CPU降频保护,系统运行频率降低影响实时性,热设计应确保在高工作量时的温度不会引发降频。
对于X86 CPU,双通道内存性能是单通道内存的2. 5倍以上;正确的热设计可使实时性提升1.4倍以上。

2.BIOS(X86平台)

BIOS 在系统中扮演着关键角色,运行于系统管理模式(SMM),负责电源管理和硬件控制。系统启动后,BIOS 持续监测系统状态,并在遇到重大故障(如 CPU 温度异常)时采取紧急措施(如降频或关机)。
对于实时系统,优化 BIOS 设置至关重要。经过优化的 BIOS 配置相比默认设置,可显著提升实时性能,差距可达 9 倍以上。

SMI(System Management Interrupts)

系统管理中断(System Management Interrupts,SMI) 是 x86 CPU 中最高优先级的特殊中断,它会强制 CPU 进入系统管理模式(System Management Mode,SMM)。SMM 是实模式的一种变体,通常用于执行 BIOS 实现的特定处理程序。在 SMM 模式下,包括操作系统在内的所有正常执行都会被暂停。
SMI 不通过中断控制器传递,而是由 CPU 逻辑在指令执行之间检测并立即调度。这种机制对实时系统带来了以下关键问题:
  • 不可预测的抢占:SMI 可以在任何时候抢占实时代码,且抢占时间不确定。内核软件无法屏蔽或抢占 SMI,甚至无法感知 SMI 的发生。
  • 上下文切换开销:进入和退出 SMM 模式时,CPU 需要保存和恢复其大部分寄存器文件,并切换到不同的 CPU 模式。对于多核系统,BIOS 可能会等待所有 CPU 内核进入 SMM 模式,然后序列化处理待处理的 SMI 请求。这种机制会引入额外的延迟。
  • 不透明的 SMM 处理程序:SMI 调用的 SMM 处理程序由 BIOS 实现,其内部逻辑对操作系统和应用程序是不透明的。某些 SMM 处理程序可能会引入显著的延迟,例如与 USB 相关的 SMI 处理程序,通常会导致约 300 微秒的延迟。
如今,几乎所有的 x86 架构台式机和服务器硬件都高度依赖系统管理中断(SMI)来执行各种内部管理操作和所谓的优化功能。然而,在嵌入式应用和实时性要求较高的场景中,SMI 的影响可能成为关键问题。
相比之下,专为嵌入式应用设计的片上系统(SoC)平台通常在实时性方面表现更优,能够更好地满足严格的实时需求。因此,在选择硬件时,强烈建议提前向供应商详细了解其对 SMI 问题的解决方案,或者通过实际测试评估硬件处理 SMI 的性能表现。随意购买一台 x86 板子并不能保证系统的实时性,必须根据具体需求进行针对性选择和验证。

3.软件

操作系统:

  • 调度算法与同步机制:
    • 调度算法(如实时调度策略:FIFO、RR等)、同步机制(如信号量、互斥锁)、优先级倒置问题、通信语义和中断处理方式等,都会影响系统的实时性。
  • 异常处理方式:
    • 中断线程化、中断上下文的处理效率。
  • 内存管理:
    • 内存访问时间不确定性:MMU(内存管理单元)、Cache(缓存)、NUMA(非统一内存访问架构)等硬件特性可能导致内存访问时间波动。
    • 惰性分配策略:如 Pagefault(缺页中断)和 CoW(写时复制)机制,可能引入额外的延迟。
    • 内存分配算法的时间不确定性:快速分配路径与慢速分配路径(涉及内存合并和回收)、OOM(内存耗尽)处理机制、Swap(交换分区)等,都会影响内存分配的确定性。
  • 实时驱动:实时驱动的设计和实现直接影响硬件操作的响应速度和确定性。

资源的分配隔离

  • CPU 分配与隔离:为实时任务分配专用的 CPU 核心,确保 L1/L2 Cache 专为实时任务服务,同时将非实时任务和多余的中断隔离到其他 CPU 核心上。
  • 中断隔离:将非实时中断分配到非实时任务的核心上,减少对实时任务的干扰。

编程语言

  • 编译型语言:
    • 如汇编、C、C++、Rust、Golang 等,这些语言通常具有较高的执行效率,但需要开发者手动管理内存和资源。
    • GC(垃圾回收)机制:某些语言(如 Golang)的垃圾回收机制可能引入不确定的延迟。
    • 链接与重定位:完全动态链接、运行时链接和运行时重定位可能增加启动时间和运行时的延迟。
  • 解释型语言与即时编译型语言:
    • 如 Python、Java 等,由于其运行时的动态特性,通常无法满足实时性要求。

实时任务设计

  • 优先级设置:合理设置任务优先级,确保高优先级任务能够及时抢占低优先级任务。
  • 任务间交互设计:优化任务间的通信和同步机制,减少竞争和阻塞。
  • 软件可维护性与时序约束:设计应具备良好的可维护性,同时确保时序约束的可分析性和可验证性。
  • 过载与容错处理:设计过载保护机制和容错处理策略,确保系统在异常情况下仍能保持实时性。
  • 算法复杂度:选择计算时间确定性的算法,避免因算法复杂度高导致的时间不确定性。

其他因素

  • 虚拟化:虚拟化技术可能引入额外的延迟和不确定性,需谨慎使用。
  • GUI(图形用户界面):GUI 通常是非实时任务,需与实时任务隔离,避免对实时性造成影响。

4. GPU

在硬件层面,GPU 与 CPU 共享 L3 Cache,因此 GUI(图形用户界面)任务可能会对实时任务的实时性产生影响。为了减少这种影响,Intel 建议根据 GUI 任务的工作负载,将 GPU 的运行频率固定在一个较低的数值。通过降低 GPU 的运行频率,可以有效减少其对 L3 Cache 的占用,从而降低对实时任务的干扰,提升系统的实时性能。

三、优化措施

原则:降低不确定性,提高可预期性,在此基础上,再提高速度,降低延时。
举例来说,如果我们需要在确定的时间内从广州到深圳,选择驾车可能会遇到红绿灯、堵车等不确定因素,导致时间难以预测。而选择动车则更具确定性,如果在此基础上选择高铁,则能进一步缩短时间,降低延迟。

1. BIOS 配置[x86]

禁用功能
禁用原因
对实时性的提升作用
Intel Hyper-Threading Technology
超线程技术通过共享执行单元模拟多个逻辑核心,可能导致实时任务与非实时任务竞争资源。
减少任务竞争,降低上下文切换开销,提高实时任务的确定性。
Intel SpeedStep
SpeedStep 动态调整 CPU 频率,可能导致频率切换时的延迟和不确定性。
固定 CPU 频率,避免频率切换带来的延迟波动,提高任务执行的确定性。
Intel Speed Shift Technology
Speed Shift 技术进一步优化频率调整,但仍可能引入频率切换延迟。
禁用后避免频率动态调整,减少延迟波动,提高实时任务的响应时间一致性。
C-States
C-States 是 CPU 的节能状态,进入和退出这些状态会引入额外的延迟。
禁用 C-States 避免 CPU 进入低功耗状态,减少唤醒延迟,提高实时任务的响应速度。
Gfx RC6
RC6 是 GPU 的节能技术,可能导致 GPU 频率动态调整,影响实时性。
禁用后固定 GPU 频率,减少 GPU 频率波动对实时任务的干扰。
GT PM Support
GT PM 是 GPU 的电源管理功能,可能导致 GPU 性能波动。
禁用后避免 GPU 电源管理带来的性能波动,提高实时任务的稳定性。
PCH Cross Throttling
PCH 交叉节流可能导致总线和外设性能受限,影响实时任务的执行。
禁用后避免总线带宽受限,确保实时任务对总线和外设的访问效率。
PCI Express Clock Gating
PCIe 时钟门控可能导致 PCIe 设备访问延迟增加。
禁用后避免 PCIe 设备访问延迟波动,提高实时任务对 PCIe 设备的访问效率。
Delay Enable DMI ASPM, DMI Link ASPM Control
DMI 链路电源管理可能导致总线访问延迟增加。
禁用后避免 DMI 链路电源管理带来的延迟波动,提高总线访问的确定性。
PCIe ASPM and SATA Aggressive LPM Support
PCIe 和 SATA 的电源管理可能导致设备访问延迟增加。
禁用后避免 PCIe 和 SATA 设备的电源管理延迟,提高设备访问的实时性。
(对于 Skylake 和 Kaby Lake,还需考虑禁用 Gfx Low Power Mode 和 USB Periodic SMI)
Gfx 低功耗模式和 USB 周期性 SMI 可能导致 GPU 和 USB 设备的延迟波动。
禁用后避免 GPU 和 USB 设备的延迟波动,提高实时任务的稳定性和响应速度。
启用功能
启用原因
对实时性的提升作用
Legacy I/O Low Latency
传统 I/O 低延迟模式优化了 I/O 设备的响应时间。
减少 I/O 设备的访问延迟,提高实时任务对 I/O 设备的访问效率。
Gfx Frequency:根据工作负载设置为尽可能低的固定值
固定 GPU 频率避免频率动态调整带来的延迟波动。
减少 GPU 频率波动对实时任务的干扰,提高实时任务的稳定性。
Memory Frequency:SA GV Fixed High
固定内存频率避免动态调频带来的延迟波动。
减少内存访问延迟波动,提高实时任务对内存访问的确定性。

OS SMI配置

默认情况下,Xenomai 核心中的 SMI(系统管理中断)问题解决代码会尝试通过识别底层芯片组来检测潜在的 SMI/SMM 相关问题。这对应于以下内核参数设置:
xenomai.smi=detect
启动 Xenomai 后,如果检测到 SMI 问题,系统会通过内核日志发出以下警告:
Xenomai: SMI-enabled chipset found, but SMI workaround disabled
此时,您需要运行 Xenomai 的延迟测试程序,重点关注是否存在病态延迟(例如超过 100 微秒的延迟),以确定系统的实时性能是否受到 SMI 等因素的影响。
如果未观察到任何病态延迟,则可以忽略此警告,并通过以下步骤关闭 SMI 检测:
  • 在内核命令行中添加以下参数,完全禁用 Xenomai 的 SMI 检测:
xenomai.smi=disabled
  • 跳过此小节的其余内容
如果确实观察到病态延迟,则说明 SMI 存在问题。Xenomai 提供了两种解决方法:

禁用所有 SMI 源

通过以下参数禁用所有 SMI 源:
xenomai.smi=enabled
禁用 SMI 后,需检查以下内容以确保系统正常工作:
  • 内核日志:不应包含以下消息:
demsg ... Xenomai: SMI workaround failed! ...
如果出现上述消息,说明此方法无效,需尝试“有选择地禁用 SMI 源”。
  • 设备功能:禁用所有SMI后系统上的每个设备(例如键盘、鼠标、NIC)仍能正常响应。
  • 系统稳定性:即使在持续的高负载条件下,主板也不会过热。如果在对系统进行压力测试时出现意外和临时重启,那么应该立即重新启用 SMI,并放弃这种方法。
  • 延迟测试:长时间测试也不再显示任何病态延迟。
如果某些设备无法正常工作或系统过热,则可能需要保留部分 SMI 源(如热控制相关的 SMI),并禁用其他 SMI 源。

有选择地禁用 SMI 源

为了有选择地控制 SMI 源,需参考英特尔芯片组文档,查找 SMI_EN 寄存器的相关信息,确定与 SMI 源对应的位值。然后,通过以下内核参数传递位掩码,Xenomai 将尝试禁用掩码中清除的 SMI 源,同时启用其他源:
xenomai.smi_mask=<enable-mask>
再次检查内核日志,确保不包含以下消息:
Xenomai: SMI workaround failed!
如果出现此消息,则无法通过 Xenomai 的 SMI 解决方法避免 SMI 问题,需检查 BIOS 中是否有可能导致 SMI 的设置。通过逐步优化禁用的 SMI 源集,尝试仅停止导致病态延迟的 SMI 源,同时保持系统的其他部分安全和稳定。每次调整后,都应重新运行 Xenomai 延迟测试以验证当前状态。

2. 硬件

除了处理器之外,内存和散热设计也对实时性有重要影响:
  • 内存优化:
    • 使用双通道内存,以提升内存带宽。
    • 尽可能选择高频率内存,以减少内存访问延迟。
  • 散热设计
    • 针对处理器的工作负载设计良好的散热结构。如果散热不足,处理器可能会因过热触发保护机制,强制降频。频率调整会导致 CPU 停顿几十到上百微秒,严重影响实时性。

3. Kernel 相关参数配置

Xenomai 基于 Linux,作为一个小的实时核与 Linux 共存。Xenomai 本身并未提供完整的硬件管理机制,许多硬件配置由 Linux 驱动管理。因此,必须通过合理配置 Linux,为 Xenomai 提供一个优化的硬件环境,使其能够充分发挥实时操作系统(RTOS)的优势。
主要宗旨:尽可能避免 Linux 的非实时部分(无论是软件还是硬件)对 Xenomai 的实时任务造成干扰。

3.1 Kernel CMDLINE

💡
注:以下配置信息中,明确提到“xenomai”的为 Xenomai 特定配置,其余为 Xenomai 和 PREEMPT-RT 的通用配置。

CPU 隔离

在多核系统中,可以通过设置内核参数 isolcpus=[CPU列表]​,将指定的 CPU 从 Linux 内核的 SMP 负载均衡和调度算法中剔除,从而将这些 CPU 专用于实时任务。例如,在一个 4 核 CPU 平台上,可以将第 3 和第 4 核隔离出来用于实时任务。
CPU 编号从 0 开始,列表的表示方法有三种:
  1. 单个 CPU:numA,numB,...,numN​
  1. 连续范围:numA-numN​
  1. 组合形式:numA,...,numM-numN​
例如:isolcpus=0,3,4-7​ 表示隔离 CPU 0、3、4、5、6、7。
GRUB_CMDLINE_LINUX="isolcpus=2,3"
以上配置仅确保 Linux 不会将普通任务调度到 CPU 2 和 CPU 3 上运行,这是基础。接下来,还需要进一步设置 Xenomai 的 CPU 隔离。

方法一:通过任务绑定 CPU

在 Xenomai 任务中,可以通过 pthread_attr_setaffinity_np()​ 函数将任务绑定到指定的 CPU 上运行。例如,将任务限制在 CPU 2 和 CPU 3 上运行:
cpu_set_t cpus; CPU_ZERO(&cpus); CPU_SET(2, &cpus);//将线程限制在指定的cpu2上运行 CPU_SET(3, &cpus);//将线程限制在指定的cpu3上运行 ret = pthread_attr_setaffinity_np(&tattr, sizeof(cpus), &cpus);
这种方法可以提高任务在指定 CPU 上的 L1 和 L2 缓存命中率,从而优化实时性能。

方法二:通过 Xenomai 内核参数隔离 CPU

通过 Xenomai 的内核参数 supported_cpus​,可以指定 Xenomai 支持的 CPU 核心。Xenomai 任务会自动分配到这些 CPU 上运行。
💡
注意:对于 Xenomai 3.2 及以上版本,supported_cpus​ 必须包含 CPU 0,否则 Xenomai 内核无法启动!
xenomai 内核参数 supported_cpus​ 参数说明:
该参数是一个 16 进制数,每位表示一个 CPU 核心。
例如,要支持 CPU 2 和 CPU 3,需要将第 2 位和第 3 位置位,即 supported_cpus=0x0C(二进制:00001100)。
GRUB_CMDLINE_LINUX="audit=0 isolcpus=2,3 xenomai.supported_cpus=0x0C"
Linux 内核参数 isolcpus=[CPU列表] 是基础配置。如果不隔离 Linux 任务,后续的 Xenomai 设置将无法生效。

Full Dynamic Tick

将 CPU 2 和 CPU 3 专用于 Xenomai 后,由于 Xenomai 调度器完全基于优先级运行,并且 Linux 任务已被从这两个 CPU 上剔除,因此 CPU 上的定时器 Tick 中断变得多余。为了避免这些不必要的 Tick 中断影响实时任务的运行,需要将这两个 CPU 配置为 Full Dynamic Tick 模式,即关闭 Tick 中断。通过添加 Linux 内核参数 nohz_full=[CPU列表]​ 实现。
💡
注意:nohz_full=[CPU列表] 仅在使用了 CONFIG_NO_HZ_FULL=y 配置构建的内核中生效。
GRUB_CMDLINE_LINUX="audit=0 isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3"

为什么通过 Linux 内核参数配置?

在双核时间子系统的分析中可以看到,每个 CPU 的时钟工作方式是由 Linux 初始化和配置的,Xenomai 只是最终接管这些配置。因此,Full Dynamic Tick 模式需要通过 Linux 内核参数进行配置。

重要注意事项

Boot CPU(通常是 CPU 0)会无条件从 nohz_full​ 列表中剔除。这是 Linux 内核的一个限制,可能会导致配置时遇到“坑”。
相关代码逻辑如下:
start_kerel() ->tick_init() ->tick_nohz_init() void __init tick_nohz_init(void) { ....... cpu = smp_processor_id(); if (cpumask_test_cpu(cpu, tick_nohz_full_mask)) { pr_warn("NO_HZ: Clearing %d from nohz_full range for timekeeping\n", cpu); cpumask_clear_cpu(cpu, tick_nohz_full_mask); } ...... }

Offload RCU callback

为了进一步优化实时性能,可以从指定的 CPU 上卸载 RCU(Read-Copy-Update)回调处理,转而使用内核线程 rcuox/N​ 来处理这些回调。通过 Linux 内核参数 rcu_nocbs=[CPU列表]​ 可以指定需要卸载 RCU 回调的 CPU 列表。这对于高性能计算(HPC)和实时工作负载非常有用,因为它可以减少指定 CPU 上的操作系统抖动,从而提高实时任务的确定性。
​rcuox/N​ 线程说明:
  • ​N​ 表示 CPU 编号。
  • ​x​ 表示 RCU 类型:
    • ​b​:RCU-bh
    • ​p​:RCU-preempt
    • ​s​:RCU-sched

配置要求

  1. 内核配置:
      • ​rcu_nocbs=[CPU列表]​ 仅在使用了 CONFIG_RCU_NOCB_CPU=y​ 配置构建的内核中生效。
      • 需要设置 RCU 内核线程(rcuc/N​ 和 rcub/N​)的调度策略为 SCHED_FIFO​,并为其分配优先级 RCU_KTHREAD_PRIO​。
  1. 优先级设置:
      • ​RCU_KTHREAD_PRIO​ 应设置为高于最低优先级线程的优先级,但低于 Xenomai 实时应用的优先级。这样可以避免 Xenomai 实时任务迁移到 Linux 后,因优先级低于 RCU 线程而影响实时性。
      • 例如,将 RCU_KTHREAD_PRIO​ 设置为 0​。

内核配置示例

在 Linux 内核配置菜单中,进行如下设置:
General setup ---> RCU Subsystem ---> (0) Real-time priority to use for RCU worker threads [*] Offload RCU callback processing from boot-selected CPUs (X) No build_forced no-CBs CPUs ( ) CPU 0 is a build_forced no-CBs CPU ( ) All CPUs are build_forced no-CBs CPUs

内核参数示例

在 GRUB 配置中添加以下内核参数:
GRUB_CMDLINE_LINUX="audit=0 isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3 rcu_nocb_poll=1024 rcupdate.rcu_cpu_stall_suppress=1"
  • rcu_nocbs=2,3:将 CPU 2 和 CPU 3 的 RCU 回调处理卸载到内核线程。
  • rcu_nocb_poll=1024:减轻每个 CPU 唤醒其 RCU 卸载线程的责任,减少唤醒频率。
  • rcupdate.rcu_cpu_stall_suppress=1:禁止显示 RCU CPU 停顿警告消息,避免不必要的日志干扰。

中断

中断隔离

在 Xenomai 用户态实时应用运行时,中断具有最高优先级,CPU必须响应中断,虽然有 ipipe 能够将非实时设备中断简单挂起,但频繁的非实时设备中断仍可能引入不可预测的延迟,影响实时任务的运行。
因此,在多核系统中,可以通过内核参数 irqaffinity=[CPU列表]​ 设置 Linux 设备中断的亲和性,指定默认处理中断的 CPU 核心。例如,将 Linux 中断限制在 CPU 0 和 CPU 1 上处理,避免非实时中断影响运行实时任务的 CPU 2 和 CPU 3。配置如下:
GRUB_CMDLINE_LINUX="audit=0 isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1"
以上只是设置 linux 中断的 affinity,只能确保运行实时任务的 CPU2、CPU3 不会收到 linux 非实时设备的中断请求,保证实时性。

实时设备中断绑定

对于 Xenomai 实时设备中断,可以通过实时驱动代码中的 xnintr_affinity()​ 函数设置中断亲和性,将实时设备中断绑定到指定的 CPU 核心(如 CPU 2 和 CPU 3)。示例代码如下:
cpumask_t irq_affinity; ... cpumask_clear(&irq_affinity); cpumask_set_cpu(2, &irq_affinity); // 绑定到 CPU 2 cpumask_set_cpu(3, &irq_affinity); // 绑定到 CPU 3 ... if (!cpumask_empty(&irq_affinity)) { xnintr_affinity(&pIp->irq_handle, irq_affinity); // 设置实时设备中断的亲和性 }
虽然 ipipe 会确保 Xenomai 实时中断在任何 CPU 上都能优先处理,但在以下情况下,建议将 Linux 中断与实时中断分开:
  • 实时设备中断较少:将实时中断绑定到特定 CPU 核心,避免与非实时中断竞争。
  • 实时设备中断较多:如果实时中断数量较多,不建议绑定到特定 CPU 核心,以避免实时中断之间相互影响。

实时设备中断处理程序

在编写 Xenomai 实时设备驱动程序时,中断处理程序应尽可能简短,以减少中断处理时间,提高实时任务的响应速度。

禁用irqbanlance

Linux 的 irqbalance​ 服务用于优化中断分配,它会根据系统负载动态调整中断分配策略:
  • Performance mode:将中断均匀分配给所有 CPU 核心,以提升性能。
  • Power-save mode:将中断集中分配给第一个 CPU 核心,以降低能耗。
为了避免非实时中断影响实时任务核心,建议禁用 irqbalance​ 服务。以 Ubuntu 为例,停止并禁用 irqbalance​ 服务的命令如下:
systemctl stop irqbalance.service systemctl disable irqbalance.service
如果需要,可以直接卸载 irqbalance​:
apt-get remove irqbalance
对于 x86 平台,还可以添加内核参数 acpi_irq_nobalance​ 和 noirqbalance​,进一步禁用 ACPI 中断平衡功能:
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance"

intel 核显配置[x86]

针对 Intel CPU 的核显(集成显卡),可以通过配置 Intel 核显驱动模块 i915​,防止集成显卡更改电源状态,从而减少对实时任务的干扰。以下是相关内核参数的配置:
GRUB_CMDLINE_LINUX="i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 i915.powersave=0"

参数说明

参数
作用
​i915.enable_rc6=0​
禁用 RC6 电源管理功能,避免显卡进入低功耗状态。
​i915.enable_dc=0​
禁用 Display C-states(显示电源状态),减少显示相关的电源管理延迟。
​i915.disable_power_well=0​
禁用电源井(Power Well)功能,避免显卡电源状态切换带来的延迟。
​i915.enable_execlists=0​
禁用 Execlists 提交模式,使用传统的 ring buffer 模式,减少调度复杂性。
​i915.powersave=0​
禁用所有电源管理功能,确保显卡始终以最高性能运行。

禁用调频

CPU 动态调频(Frequency Scaling)会引入不可预测的延迟,严重影响实时任务的确定性。通过内核参数 cpufreq.off=1 可以禁用调频功能,确保 CPU 频率固定,从而提高实时性。
GRUB_CMDLINE_LINUX="cpufreq.off=1"

调频对实时性的影响

动态调频会导致以下问题:
  1. 频率切换延迟:CPU 频率切换时,可能导致几十到上百微秒的停顿。
  1. 不确定性:频率的动态调整使得任务执行时间难以预测,影响实时任务的确定性。
禁用调频后,CPU 将始终以固定频率运行,避免了频率切换带来的延迟波动,显著提高了系统的实时性能。

hugepages

使用大页(Hugepages)可以显著降低缺页异常(Page Fault)的频率,并提高 TLB(Translation Lookaside Buffer)的命中率,从而减少内存分配的开销。以下是通过内核参数配置大页的示例:
GRUB_CMDLINE_LINUX="hugepages=1024 "

参数说明

  • hugepages=1024:一次性分配 1024 个 2MB 的大页,总计 2GB 的大页内存。如果需要 1GB 的大页,可以通过 hugepagesz=1Ghugepages=N 组合实现。

优点

  1. 减少缺页异常:大页减少了内存分页的数量,从而降低了缺页异常的发生频率。
  1. 提高 TLB 命中率:大页减少了 TLB 的未命中率,提高了内存访问效率。
  1. 降低内存分配频率:大页减少了内存分配的次数,提高了内存管理的效率。

禁用 NUMA 平衡

NUMA(Non-Uniform Memory Access)平衡功能会根据任务的处理相关性动态调整内存分配策略,可能导致缓存数据在不同 NUMA 节点之间迁移,从而引入额外的延迟。对于实时系统,建议禁用 NUMA 平衡功能,以确保内存访问的确定性。
通过以下内核参数禁用 NUMA 平衡:
GRUB_CMDLINE_LINUX="numa_balancing=disable"

参数说明

  • numa_balancing=disable:禁用 NUMA 平衡功能,防止任务的内存页在不同 NUMA 节点之间迁移。

优点

  1. 减少缓存迁移:避免缓存数据在 NUMA 节点之间迁移,降低内存访问延迟。
  1. 提高内存访问确定性:确保内存访问的稳定性和可预测性,适合实时任务的需求。

nmi_watchdog[x86]

NMI(Non-Maskable Interrupt,不可屏蔽中断)Watchdog 是 Linux 开发者为了调试和检测内核挂起(Kernel Hang)问题而引入的特性。现代多核 x86 架构均支持 NMI Watchdog。
NMI 之所以不可屏蔽,是因为它的监视目标是整个内核。即使内核在关中断的情况下陷入死循环,NMI 仍然能够触发并恢复系统。
Linux 中有两种 NMI Watchdog:
  1. I/O APIC Watchdognmi_watchdog=1):通过 I/O APIC 触发 NMI。
  1. Local APIC Watchdognmi_watchdog=2):通过 Local APIC 触发 NMI。
它们的触发机制不同,但触发后的操作类似。一旦启用 NMI Watchdog,每个 CPU 的 Local APIC 的 LINT0 线都会关联到 NMI,从而周期性地触发 NMI。如果系统正常运行,NMI Watchdog 仅更新时间计数;如果系统异常(默认 5 秒内没有普通外部中断),NMI Watchdog 会立即介入并中止当前程序的运行。

关闭 NMI Watchdog

NMI Watchdog 的周期性中断可能会影响 Xenomai 实时任务的性能。因此,在实时系统中建议关闭 NMI Watchdog,通过以下内核参数实现:
nmi_watchdog=0

禁用超线程

超线程技术(Hyper-Threading)通过共享执行单元模拟多个逻辑核心,可能导致实时任务与非实时任务竞争资源,从而引入不确定性。为了确保实时任务的确定性,建议禁用超线程,通过以下内核参数实现:
noht

综合配置示例

将关闭 NMI Watchdog 和禁用超线程的配置与其他优化参数结合,示例如下:
GRUB_CMDLINE_LINUX="audit=0 isolcpus=2,3 xenomai.supported_cpus=0x0c xenomai.smi_mask=1 xenomai.smi=detect nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 i915.powersave=0 nmi_watchdog=0 noht"

禁用 Soft-Lockup 检测器

Soft-Lockup 检测器是 Linux 内核用于检测进程在 CPU 上执行时间过长的机制。当某个进程在 CPU 上执行的时间超过 soft-lockup 阈值(默认 120 秒)时,内核会触发回溯跟踪日志记录,这可能会对实时任务的性能产生干扰。为了减少这种干扰,可以通过内核参数禁用 soft-lockup 检测器。

内核参数配置

通过以下内核参数禁用 soft-lockup 检测器:

综合配置示例

将禁用 soft-lockup 检测器的配置与其他优化参数结合,示例如下:
GRUB_CMDLINE_LINUX="audit=0 isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 i915.powersave=0 nmi_watchdog=0 nosoftlockup"

CPU特性[x86]

针对 Intel 处理器的实时性优化,可以通过以下内核参数配置来减少电源管理、状态切换和中断处理带来的延迟,从而提高系统的确定性和响应速度。

内核参数配置

参数
作用
​nosmap​
禁用 SMAP(Supervisor Mode Access Prevention),减少内存访问检查的开销。
​nohalt​
禁用省电功能 PAL_HALT_LIGHT​,减少中断唤醒延迟,适合实时系统和网络服务器。
​mce=ignore_ce​
忽略 Machine Check Errors(MCE),避免因硬件错误检测引入的延迟。
​idle=poll​
在空闲循环中使用轮询而非 HLT 指令,减少唤醒延迟,但会增加功耗。
​clocksource=tsc tsc=reliable​
使用 TSC(Time Stamp Counter)作为系统时钟源,提高时钟精度和稳定性。
​intel_idle.max_cstate=0​
禁用 Intel 的 C-state 空闲状态,回退到 acpi_idle​。
​processor.max_cstate=0​
限制处理器的最大 C-state 状态,减少状态切换带来的延迟。
​intel.max_cstate=0​
限制 Intel 处理器的最大 C-state 状态。
​processor_idle.max_cstate=0​
限制处理器空闲状态的最大 C-state。
​hpet=disable​
禁用 HPET(High Precision Event Timer),使用 TSC 作为时钟源。
GRUB_CMDLINE_LINUX="audit=0 xenomai.allowed_group=1234 isolcpus=2,3 xenomai.supported_cpus=0x0D xenomai.smi_mask=1 xenomai.smi=detect irqaffinity=0,1 nohz_full=2,3 rcu_nocbs=2,3 rcu_nocb_poll rcupdate.rcu_cpu_stall_suppress=1 acpi_irq_nobalance numa_balancing=disable cpufreq.off=1 nosmap nosmt noirqbalance hugepages=1024 i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 processor.max_cstate=0 intel.max_cstate=0 processor_idle.max_cstate=0 intel_idle.max_cstate=0 clocksource=tsc pcie_asmp=off tsc=reliable nmi_watchdog=0 noht nosoftlockup intel_pstate=disable idle=poll nohalt mce=ignore_ce hpet=disable"

3.2 内核构建配置

在构建内核时,除了之前提到的配置(如 CONFIG_NO_HZ_FULL=yCONFIG_RCU_NOCB_CPU=yRCU_KTHREAD_PRIO=0),还需要进行以下实时性相关的配置:

内核配置选项

配置选项
作用
​CONFIG_MIGRATION=n​
禁用任务迁移功能,减少任务在 CPU 核心间迁移带来的开销和延迟。
​CONFIG_MCORE2=y​ [x86]
启用对 Intel Core 2 处理器的优化支持(仅适用于 x86 架构)。
​CONFIG_PREEMPT=y​
启用完全可抢占内核(Preemptible Kernel),减少任务调度延迟。
​ACPI_PROCESSOR=n​ [x86]
禁用 ACPI 处理器驱动,避免电源管理功能引入的延迟(仅适用于 x86 架构)。
​CONFIG_CPU_FREQ=n​
禁用 CPU 频率调节功能,避免动态调频带来的延迟波动。
​CONFIG_CPU_IDLE=n​
禁用 CPU 空闲状态管理,避免进入和退出空闲状态带来的延迟。

配置后的验证

完成上述配置后,可以使用 latency​ 测试工具观察配置前后的性能变化。需要注意的是:
  1. Timer-IRQ Latency 测试
      • 使用 latency -t2​ 命令测试 Timer-IRQ 的延迟时,Xenomai 默认使用 CPU 0 的定时器。
      • 由于 Boot CPU(通常是 CPU 0)会无条件从 nohz_full=[CPU列表]​ 中剔除,因此 latency -t2​ 测试结果可能没有明显改善,甚至平均值可能变差。
      • 此外,Linux 中断的亲和性被设置为 CPU 0 处理,这些中断也会对 Timer-IRQ 的延迟产生一定影响。
  1. Xenomai 内核定时器亲和性问题
      • 最近发现 Xenomai 内核定时器默认绑定到 CPU 0 的问题已被社区修复,建议使用最新版本的 Xenomai 内核。
2021.5添加-- 最近发现xenomai内核定时器affinity为cpu0的问题已被社区修复。

三、软件优化

在实时系统中,软件设计和实现对系统的实时性能有着至关重要的影响。以下是一些关键的软件优化措施:

1. 使用静态编译语言

  • 推荐语言:C、C++、Rust 等静态编译语言。
  • 优点:静态编译语言生成的代码执行效率高,运行时开销小,适合对性能要求严格的实时任务。

2. 编写高性能的代码

  • 优化算法:选择时间复杂度低、确定性高的算法。
  • 减少系统调用:尽量减少对操作系统内核的调用,避免上下文切换带来的开销。
  • 避免阻塞操作:确保实时任务不会因 I/O 操作或其他阻塞调用而延迟。

3. 分支优化

  • 规律性分支:尽量让分支条件具有规律性,便于 CPU 的分支预测器优化。
  • 使用 likely()​/unlikely()​:通过提示编译器优化分支预测,减少分支预测错误带来的性能损失。
  • 无分支代码:在关键路径中尽量编写无分支代码,避免分支预测失败的开销。

4. 利用 Cache 局部性原理

  • 数据局部性:将频繁访问的数据放在相邻的内存位置,提高 Cache 命中率。
  • 防止伪共享:确保不同线程访问的数据不在同一 Cache 行中,避免 Cache 行竞争。

5. 合理分配任务优先级

  • 优先级设置:根据任务的实时性要求合理设置优先级,确保高优先级任务能够及时抢占低优先级任务。
  • 避免优先级反转:使用优先级继承或优先级天花板协议,防止低优先级任务阻塞高优先级任务。

6. 尽量使用静态库

  • 静态链接:使用静态库而非动态库,减少运行时链接的开销。
  • 优点:静态链接的代码加载速度快,运行时性能更稳定。

7. 避免实时任务中进行动态内存分配

  • 动态内存分配问题:动态内存分配(如 malloc​)可能导致不可预测的延迟,甚至触发内存碎片整理。
  • 替代方案:
    • 使用预分配的内存池。
    • 在任务初始化阶段分配所需内存。
    • 避免在实时任务的关键路径中进行内存分配。

8. 驱动程序中断处理尽可能短

  • 中断处理程序:确保中断处理程序尽可能简短,快速完成必要操作后退出。
  • 延迟处理:将非关键操作推迟到中断下半部(Bottom Half)或任务上下文中处理。

四、优化结果对比

笔者对上述各项优化配置进行了前后对比测试,结果显示实时性均有不同程度的改善。以下是基于 i5-7200U 8GB 单通道 DDR4,64GB eMMC 5.0 平台的测试结果(未使用 Intel RDT 技术)。
1-3 在已裁剪桌面下,压力加了内存。

1. 原始性能测试。

仅使用 Xenomai,并启用了以下内核配置:
  • CONFIG_MIGRATION=n
  • CONFIG_MCORE2=y [x86]
  • CONFIG_PREEMPT=y
  • ACPI_PROCESSOR=n [x86]
  • CONFIG_CPU_FREQ=n
  • CONFIG_CPU_IDLE=n
优化项
配置与否
BIOS
NO
Linux
NO
Full Dynamic Tick
NO
Offload RCU callback
NO
Full desktop
NO
stress
​-c 10 -m 4​
notion image

2. 优化 BIOS 设置

在原始配置的基础上,优化了 BIOS 设置。
优化项
配置与否
BIOS
YES
Linux
NO
Full Dynamic Tick
NO
Offload RCU callback
NO
Full desktop
NO
stress
​-c 10 -m 4​
notion image

3. Linux配置优化。

在优化 BIOS 的基础上,进一步优化了 Linux 配置,包括:
  • 启用 Full Dynamic Tick
  • 启用 Offload RCU callback
优化项
配置与否
BIOS
YES
Linux
YES
Full Dynamic Tick
YES
Offload RCU callback
YES
Full desktop
NO
stress
​-c 10 -m 4​
notion image

4-6 未添加内存压力

4. 裁剪桌面。

在完成所有优化配置后,对比了保留完整 Ubuntu 桌面和裁剪桌面后的实时性能差异。

保留完整桌面

优化项
配置与否
BIOS
YES
Linux
YES
Full Dynamic Tick
YES
Offload RCU callback
YES
Full desktop
YES
stress
​-c 10​
notion image

裁剪桌面后:

notion image

裁剪前后对比:

notion image

5. Full Dynamic Tick启用前后对比

在裁剪桌面后,对比了 CPU 0 未启用 Full Dynamic Tick 和 CPU 1 启用 Full Dynamic Tick 的性能差异,分别在加压和未加压情况下进行测试。
优化项
配置与否
BIOS
YES
Linux
YES
Full Dynamic Tick
CPU 0: NO; CPU 1: YES
Offload RCU callback
CPU 0: NO; CPU 1: NO
Full desktop
NO
stress
​-c 10​
notion image
notion image

对比分析

  • 最坏情况:启用 Full Dynamic Tick 后,最坏情况下的延迟(Worst-case Latency)没有明显改善。
  • 4us 以上的延迟:启用 Full Dynamic Tick 后,4us 以上的延迟显著减少,表明系统在高负载下的响应更加稳定。
notion image

6.桌面、rcu、tick前后比对

对比了以下两种配置的实时性能:
  1. 带桌面、未启用 rcu_nocb​、未启用 Full Dynamic Tick
  1. 裁剪桌面、启用 rcu_nocb​、启用 Full Dynamic Tick
优化项
配置变化
BIOS
YES → YES
Linux
YES → YES
Full Dynamic Tick
NO → YES
Offload RCU callback
NO → YES
Full desktop
YES → NO
stress
​-c 10​
notion image

7.总对比

综合对比了优化前后的实时性能,配置变化如下:
优化项
配置变化
BIOS
NO → YES
Linux
NO → YES
Full Dynamic Tick
NO → YES
Offload RCU callback
NO → YES
Full desktop
YES → NO
stress
​-c 10 -m 4​
notion image

四、实时性能测试

X86_64平台

以下是基于 Intel 赛扬 3865U @1.8GHz 平台的 应用空间任务Jitter 实时性能测试结果。测试环境如下:
硬件/软件
配置
CPU
Intel 赛扬 3865U @1.8GHz
Kernel
Linux 4.4.200
操作系统
Ubuntu 16.04
内存
8GB DDR3-1600 双通道
存储
64GB eMMC

测试条件

  • 使用 stress​ 工具施加压力:
    • stress -c 10 -m 4
  • 同时运行一个 QT 应用程序,绘制 2D 曲线图,QT 应用的 CPU 占用率为 99%。
测试时间:211:04:55
测试命令:测试用户空间任务的实时性,优先级为 99,任务周期为 100us,结果输出到 result.txt​:
latency -t0 -p 100 -P 99 -h -g result.txt

测试结果

经过接近 10 天的测试,result.txt​ 中的延迟分布结果如下:
# 211:04:55 (periodic user-mode task, 100 us period, priority 99) # ----lat min|----lat avg|----lat max|-overrun|---msw| # 0.343| 1.078| 23.110| 0| 0| # Xenomai version: Xenomai/cobalt v3.1 # Linux 4.4.200-xeno ...... # I-pipe releagese #20 detected # Cobalt core 3.1 detected # Compiler: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12) # Build args: --enable-smp --enable-pshared --enable-tls PKG_CONFIG_PATH=:/usr/xenomai/lib/pkgconfig:/usr/xenomai/lib/pkgconfig0 1 0.5 1599357037 1.5 1621130106 2.5 56618753 3.5 4386985 4.5 3848531 5.5 3556704 6.5 3353649 7.5 3033218 8.5 2560133 9.5 2035075 10.5 1516866 11.5 1038989 12.5 680815 13.5 417124 14.5 224296 15.5 115165 16.5 58075 17.5 27669 18.5 11648 19.5 4648 20.5 1646 21.5 467 22.5 38 23.5 1

结果分析

  • 最小延迟:0.343 us
  • 平均延迟:1.078 us
  • 最大延迟:23.110 us
测试结果表明,Xenomai 在用户空间任务中表现出色,实时性能优异。如果使用内核空间任务,实时性会更好。当然,这仅反映了操作系统提供的实时性能,实际应用中还需结合应用程序的设计进行优化。

BIOS 的影响

X86 处理器的实时性与 BIOS 配置密切相关。通常,BIOS 会优先优化 CPU 的吞吐量(如启用超线程、电源管理、动态调频等)。如果能够针对实时系统优化 BIOS 配置,实时性能将进一步提升。如下图所示,优化后的平均抖动几乎在 100 纳秒以内。
notion image

ARM64平台(瑞芯微RK3588)

在 RK3588 平台上,对比了内核参数配置前后的实时性能。测试结果显示,GPU 和 NPU 工作正常,同等压力下实时性能显著提升。
notion image
notion image

相关链接

作者:wsg1100
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
 
 
欢迎加入喵星计算机技术研究院,原创技术文章第一时间推送。
notion image
 
【转载】为什么Linux不是实时操作系统 - 沐多 - 博客园Armbian Debian 11 升级到 Debian12