尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

使用PREEMPT_RT的实时Linux(一、理解延迟并使用 cyclictest 测量延迟)

使用PREEMPT_RT的实时Linux(一、理解延迟并使用 cyclictest 测量延迟) 翻译PREEMPT_RT Latency: Measure It With cyclictest (Part 1)一、介绍Linux上的实时性是指有界的、可预测的最坏情况调度延迟而不是更高的吞吐量它是用rt-tests库里的cyclictest测量的——通过比较期望的和实际的唤醒实际得到。推荐的基本指令为cyclictest --mlockall --smp --priority80 --interval200 --distance0在理想负载下运行几分钟得到的最大延迟就是用来判断你的任务截止时间的值。PREEMPT_RT通过睡眠自旋锁、中断线程化、优先级继承把内核中的大部分都设为是可以打断的这是从6.12版本开始被主内核支持的。延迟是指一个任务应该在什么时间开始运行和这个任务实际上什么时候开始运行中间的这段时间差。那么什么是Linux上的“实时性”呢怎么测量这个实时性二、准备一台可以以root身份运行Linux的机器可以是普通的x86_64笔记本或者是单板计算机。目前还不需要一个实时内核可以先测量标准内核作为对比。rt-tests包它提供了cyclictest。熟悉基本的shell和sudo操作三、PREEMPT_RT对内核做了什么改动标准的Linux内核是为了吞吐量设计的。它会让一个任务等待一会儿如果这样能让系统可以完成更多的工作。实时系统具有相反的特性。它们需要有界、可预测的最坏情况响应时间即使平均吞吐量会更低。PREEMPT_RT是实现这些功能所改变的内核部分。发生改变的内核部分即PREEMPT_RT包括可抢占自旋锁。大部分类型为spinlock_t的内核锁被转换为基于rt-mutex的可睡眠锁。这意味着内核里持有这种锁的代码可以被打断从而高优先级任务不需要等待。线程化中断句柄。运行在内核线程里的中断句柄可以被调度和打断而不是在硬中断上下文中阻塞所有操作。优先级继承。内核内置锁支持优先级继承这限制了经典的优先级反转问题也就是低优先级会阻塞高优先级任务。一小部分锁类型为raw_spinlock_t仍然是不可抢占的因为它们要保护最底层的内核路径。最重要的是借助PREEMPT_RT内核的大部分可以被打断这在高优先级任务运行前降低了最坏情况时间。一个里程碑式PREEMPT_RT现在不再是通用版的一个out-of-tree分支了。核心实时支持被融入到Linux 6.12版本中了在2024年末发布而且实时架构可以在x86_64和arm64上实现。四、这里的延迟指的是什么当我们测量实时性能时不是要测量一个程序跑得多快。我们是在测量调度延迟任务应该被唤醒的瞬间和实际开始运行的瞬间这两者之间的时间差。如果一个任务被设置为每200微秒唤醒一次但一次周期中会延迟30微秒才被唤醒那么这30微秒就是这个周期内的延迟。最重要的数字是测量到的最大延迟因为它决定了系统是否能满足截止时间。五、安装测量工具工具是cyclictest这是由Thomas Gleixner编写的rt-tests套件的一部分现在是kernel项目的一部分。在 Debian或者Ubuntu中sudo apt updata sudo apt install rt-tests如果你的发行版没有提供它可以从官方源中构建git clone git://git.kernal/org/pub/scm/utils/rt-tests/rt-tests.git cd rt-tests make sudo make install有两种方法确认当前是否处于实时内核中uname -v cat /sys/kernal/realtime如果 /sys/kernal/realtime 不存在或者 uname -v 没有提到 PREEMPT_RT就是在标准的kernal里。六、正确运行 cyclictest不带参数运行 cyclictest 是没有用的它创建一个周期是1毫秒的单线程几乎不能测量任何东西。Linux 基金会 real-time 文档给出了一个适用于大部分 SMP 系统的指令sudo cyclictest --mlockall --smp --priority80 --interval200 --distance0这是每个参数的意思--mlockall 锁定进程内存使之不能被换出从而消除缺页异常这一延迟来源--smp 在每个 CPU 核心上运行一个测量线程每个线程都绑定自己的核心--priority80 把测量线程作为 SCHED_FIFO real-time 线程运行优先级为80--interval200 把第一个线程的唤醒周期设置为 200 微秒--distance0 让每个线程都是相同的唤醒周期而不是相互之间有错开在内部实现上由一个非real-time主线程启动测量线程这个主线程通过 clock_nanosleep 睡眠通过一个周期定时器唤醒。每一个周期都会记录期望的和实际的唤醒时间之间的差然后由主线程打印这些数据。让这个测试运行几分钟最坏情况的时间是很少见的因此短时间运行不能完全体现真实系统。CtrlC可以停止。七、读取输出实时更新的输出的每一行代表一个测量线程例如T: 0 (821) P:80 I:200 C: 518063 Min: 1 Act: 1 Avg: 1 Max: 15 T: 1 (822) P:80 I:200 C: 518050 Min: 1 Act: 2 Avg: 1 Max: 23各列的含义如下T——线程索引和它的线程IDP——real-time优先级I——唤醒周期单位是微秒C——计数目前已经测量了几个周期MinAvgMax——观测到的最小、平均、最大延迟单位是微秒Act——最近一个周期的延迟延迟的默认单位是微秒添加参数 --nsecs 可以看纳秒。添加 --histogram400 可以得到延迟图的数据用来画出延迟的直方图。八、解读 PREEMPT_RT 延迟结果最大 PREEMPT_RT 延迟是最重要的数值。平均值一般都是很小的不能看出最坏情况下的性能。在一个标准、非 real-time 内核下最大延迟可能是几百微秒到几毫秒。在一个正确配置的 PREEMPT_RT 系统中最大延迟数值一般要远低于此而且更重要的是这个值很稳定。不存在一个“好”的值。延迟是否可接受和你关系的任务的截止时间有关。一个每1毫秒运行一次的电机控制环和一个每10毫秒填充一次的音频缓冲区它们的延迟容忍度是不同的。先决定任务的 deadline再判断测得的最大延迟是否满足。为了使得对比更有意义要在系统在真实负载情况下运行 cyclictest一个空闲的系统会给出最优的结果。一个常用的方法就是在另一个终端运行一个负载生成程序比如并行内核构建或者stress-ng工具。OSADL会发布使用 cyclictest 测得的连续延迟图可以作为不同硬件平台上的延迟量级的参考。一个局限性cyclictest 结果偏乐观的。它的线程是从最近的路径里用定时器直接唤醒的。实际应用中会使用额外的间接层因此延迟会比 cyclictest 报告的要高。应该把这个值当作是最坏情况延迟的下界而非准确值。九、核心要点总结Real-time 意思是有界、可预测的最坏情况下延迟而非更大的吞吐量PREEMPT_RT 使得 kernal 的大部分都是可打断的通过可抢占自旋锁、线程化中断、优先级继承实现在6.12版本中融入主kernal中rt-tests 中的 cyclictest 通过比较期望和实际的唤醒时间来测量 PREEMPT_RT延迟使用真实的测试指令如 cyclictest --mloclall --smp --priority80 --interval200 --distance0在负载下运行几分钟读取最大延迟和任务的 deadline 相比结果只能作为真实延迟的下界。
返回列表