8.4通过延迟补偿来提高实时性
8.4 通过延迟补偿来提高实时性
延迟补偿的基本原理,不是改变时钟本身的精度,而是主动地、提前地设置定时器的到期时间,以“预支”(anticipate)掉已知的、系统固有的响应延迟。
在实时系统中,从定时器到期(Timer Shot)到目标代码(中断处理程序 IRQ、内核任务 Kernel 或用户空间线程 User)实际开始执行之间存在不可避免的延迟。
延迟来源包括硬件因素(如硬件定时器重编程所需的时间、总线传输、缓存未命中)和软件因素(如关中断代码执行、调度延迟、内核态用户态切换等)。
Gravity (重力值) 是一个静态调整值(以纳秒为单位)。它的作用是将定时器的触发时间点提前(Anticipate)Gravity (重力值) 所表示的时间量。
例如,如果一个用户空间线程需要在绝对时间点 T 被唤醒,但系统从定时器到期到唤醒该线程通常需要 G 纳秒(用户重力),那么定时器会被设置为在T - G时刻到期。这样,尽管有延迟 G,线程实际被唤醒的时间点会更接近预期的 T。
Xenomai 3三个独立的重力值,分别对应定时器触发后激活的不同执行上下文:
irq重力值: 中断发生到执行实时中断处理程序 (Real-time IRQ handler)的固有延迟kernel重力值: 从中断处理程序执行结束,到开始执行内核态 RTDM 线程 (Kernel task)的固有延迟user重力值: 从中断处理程序执行结束,到开始执行用户态用户空间 Xenomai 实时线程 (User-space thread)的固有延迟
# cat /proc/xenomai/clock/coreclk gravity: irq=0 kernel=5000 user=5000 devices: timer=arch_sys_timer, clock=<Linux clocksource> watchdog: on ticks: 19251279868217 (1182 49b2b139)如何修改 Gravity (重力值)?
- 编译时设置默认值
默认情况下,Gravity (重力值) 的值是 0,表示系统没有对定时器进行补偿。
--- Xenomai/cobalt Latency settings ---> (0) User scheduling latency (ns) (0) Intra-kernel scheduling latency (ns) (0) Interrupt latency (ns)- 运行时手动修改 Gravity (重力值)
通过写入/proc/xenomai/clock/coreclk文件(使用后缀i,k,u或组合)来动态调整不同上下文的重力值,以优化系统实时性能。
/* change the user gravity (default) */ # echo 3000 > /proc/xenomai/clock/coreclk /* change the IRQ gravity */ # echo 1000i > /proc/xenomai/clock/coreclk /* change the user and kernel gravities */ # echo "2000u 1000k" > /proc/xenomai/clock/coreclk- 运行时自动调整 Gravity (重力值)
通过 autotune 工具,可以自动调整 Gravity (重力值),以优化系统实时性能。
编译内核时,需打开 Auto-tuning 选项:
--- Xenomai/cobalt Core features ---> <*> Auto-tuning值得注意的是,调整了 Gravity (重力值) 后,如果提前触发量设置的过大,可以能导致延迟出现负数的情况。因此,需要根据系统的实际情况,合理设置 Gravity (重力值)。
参考:https://doc.xenomai.org/v3/html/MIGRATION/index.html
