引言
随着Linux 内核发展,通过优化内核调度机制和中断响应能力,显著降低系统延迟并提高响应的确定性,使其适用于对时间敏感的工业控制、机器人、自动化、音视频处理等关键领域。它不仅保留了 Linux 强大的软硬件兼容性和开源生态优势,为高精度任务调度提供了可靠的操作系统基础。如何测试linux系统的实时性能,本文提供了一种方式——cyclictest工具。
目录
一、rt-tests安装
rt-tests
(Real-Time Tests)是一个用于测试 Linux 实时性能的工具集,它包含多个用于测量系统响应时间、调度延迟、中断处理延迟等关键指标的程序。
cyclictest
是 rt-tests
工具包中的其中一个核心组件。
rt-tests包含的
常见的工具:
工具名称 | 功能说明 |
---|---|
cyclictest |
最常用的实时性测试工具,通过多线程定时唤醒机制测试系统最大延迟 |
hrtimer-test |
测试 hrtimer 子系统的精度和稳定性 |
pi-stress |
测试优先级继承(Priority Inheritance)机制是否正常工作 |
sigwaittest |
测试信号等待行为的实时性 |
irqsoff , preemptoff |
跟踪关闭中断或抢占的时间点,用于分析延迟来源(需 trace-cmd 配合使用) |
- 在线直接安装
对于基于Debian的发行版(如Ubuntu),可以使用apt-get命令来安装
sudo apt-get update
sudo apt-get install rt-tests
- 离线源码安装
1)使用git下载rt-tests源码
git clone git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git
如在windows下使用get bash下载rt-tests源码
2)将源码包复制到目标设备上。
3)进入rt-tests目录,编译后安装
cd rt-tests
make
sudo make install
二、cyclictest命令
在 rt-tests
中,cyclictest
是最常被使用的工具之一,很多人口语 中的rt-tests
,实际上就是在说 cyclictest
。
cyclictest的功能如下:
- 直观地反映系统最大延迟
- 支持多线程、绑定 CPU、设置优先级等高级功能
- 输出包括最小 / 最大 / 平均延迟,以及可选的直方图数据
- 可用于对比不同内核配置或硬件平台的实时性差异
1、cyclictest命令的使用
注意:cyclic使用时需要使用root权限,可以使用sudo或直接在root用户下执行。
2、cyclictest参数说明
提示:加粗参数项为常用参数。
短选项 | 长选项 | 参数 | 释义 |
---|---|---|---|
-a |
--affinity[=CPUSET] |
[CPUSET] |
将线程绑定到特定 CPU 上运行。若未指定,则每个线程按编号绑定到对应核心;若指定了 CPU 集合,则轮询分配。 |
-A |
--aligned=USEC |
USEC |
对齐线程唤醒时间,偏移为指定微秒数。 |
-b |
--breaktrace=USEC |
USEC |
当延迟超过指定微秒数时发送断点追踪命令。 |
-c |
--clock=CLOCK |
CLOCK |
选择使用的时钟源:<br>0 = CLOCK_MONOTONIC(默认)<br>1 = CLOCK_REALTIME |
--default-system |
无 | 不尝试调整系统设置(如电源管理),用于测试未优化状态下的性能。 | |
-d |
--distance=DIST |
DIST |
设置多个线程之间的间隔距离(单位:微秒),默认值为 500。 |
-D |
--duration=TIME |
TIME |
指定测试运行的时间长度。可加后缀 m(分钟)、h(小时)、d(天)。例如:-D 10m 表示运行10分钟。 |
-F |
--fifo=<path> |
<path> |
创建一个命名管道,并将统计结果写入该管道。 |
-h |
--histogram=US |
US |
输出延迟直方图,最大跟踪延迟为 US 微秒。所有线程使用相同优先级。 |
-H |
--histofall=US |
US |
同 -h,但增加一列汇总信息。 |
--histfile=<path> |
<path> |
将延迟直方图输出到指定文件,而非标准输出。 | |
-i |
--interval=INTV |
INTV |
设置线程基础间隔时间(单位:微秒),默认为 1000。 |
--json=FILENAME |
FILENAME |
将最终结果以 JSON 格式写入指定文件。 | |
--laptop |
无 | 节省电池电量模式运行(实时性较差)。 | |
--latency=PM_QOS |
PM_QOS |
设置电源管理延迟目标值,写入 /dev/cpu_dma_latency 文件。默认为 0。 |
|
-l |
--loops=LOOPS |
LOOPS |
设置循环次数,默认为 0(无限循环)。 |
--mainaffinity=CPUSET |
CPUSET |
设置主控制线程运行的 CPU,不影响测量线程。 | |
-m |
--mlockall |
无 | 锁定当前及未来内存分配,防止交换到磁盘。 |
-M |
--refresh_on_max |
无 | 只有在新的最大延迟出现时才更新屏幕,节省带宽。 |
-N |
--nsecs |
无 | 以纳秒代替微秒显示结果。 |
-o |
--oscope=RED |
RED |
示波器模式,减少冗余输出,RED 为压缩比例。 |
-p |
--priority=PRIO |
PRIO |
设置最高优先级线程的优先级数值。 |
--policy=NAME |
NAME |
设置测量线程的调度策略:<br>other / normal / batch / idle / fifo / rr | |
--priospread |
无 | 从指定优先级开始依次分配不同优先级给各线程。 | |
-q |
--quiet |
无 | 仅在退出时打印摘要信息。 |
-r |
--relative |
无 | 使用相对定时器而非绝对定时器。 |
-R |
--resolution |
无 | 检查时钟分辨率,多次调用 clock_gettime() 并通过 -X 输出列表。 |
--secaligned [USEC] |
[USEC] |
对齐线程唤醒时间为整秒时间点,并加上可选偏移。 | |
-s |
--system |
无 | 使用 sys_nanosleep 和 sys_setitimer 系统调用进行测试。 |
-S |
--smp |
无 | 标准 SMP 测试:启用 -a -t ,并使所有线程具有相同优先级。 |
--spike=<trigger> |
<trigger> |
记录所有超过触发值的延迟尖峰。 | |
|
[num of nodes] |
设置最多记录的尖峰数量,默认为 1024。 | |
--smi |
无 | 启用 SMI(系统管理模式)计数功能。 | |
-t |
--threads[=NUM] |
[NUM] |
启动与 CPU 数量相同的线程;若指定 NUM,则启动 NUM 个线程。 |
--tracemark |
无 | 当 -b 触发的延迟超出阈值时写入 trace mark。 |
|
-u |
--unbuffered |
无 | 强制不缓冲输出,便于实时处理。 |
-v |
--verbose |
无 | 输出详细统计数据,格式:n:c:v (任务号、计数、值,单位为微秒)。 |
--dbg_cyclictest |
无 | 打印调试信息,用于调试 cyclictest 本身。 | |
-x |
--posix_timers |
无 | 使用 POSIX 定时器而非 clock_nanosleep。 |
三、cyclictest测试示例
1、测试环境
设备:树莓派5B(4G)开发板
CPU:ARM Cortex-A76 4核心4线程
内核:Linux raspberrypi 6.12.25+rpt-rpi-2712 #1 SMP PREEMPT
Debian 1:6.12.25-1+rpt1 (2025-04-30) aarch64 GNU/Linux
cyclictest版本:V2.40
2、测试参数
sudo cyclictest -a -t4 -p99 -i1000 -h1000 -l10000
参数解释:
-a
:自动将四个线程分别绑定到四个CPU核心上。-t4
:启动四个线程进行测试。-p99
:设置线程的优先级为99,确保它们能够尽可能快地响应。-i1000
:设置基础间隔时间为1000微秒(即1毫秒)。-h1000
:记录延迟的直方图,最大延迟为1000微秒。- -l10000:设置每个线程执行 10,000 次循环后停止,如果不设置默认无限循环。
3、结果分析
/dev/cpu_dma_latency set to 0us
:表示系统已禁用节能状态(C-states),以获得更精确的实时性能。policy: fifo
:线程使用的是 FIFO 实时调度策略。loadavg
:系统的负载平均值(这里非常低,适合测试)。
字段 含义 T: 0
线程编号(Thread 0) (3642)
线程对应的 Linux 进程 PID P:99
线程优先级(FIFO 调度下的优先级等级) I:1000
基础间隔时间(单位:微秒) C: 10000
已完成的循环次数(即定时器唤醒次数) Min:
最小延迟(单位:微秒) Act:
当前实际延迟(最新一次测量) Avg:
平均延迟 Max:
最大延迟(整个测试过程中最高的延迟)
# Histogram 直方图输出
000000 000000 000000 000000 000000
000001 000011 000004 000003 000005
000002 001511 003247 001081 000809
......
直方图数据解析 ,第一列为延迟值(如 0μs、1μs、2μs),后面的数字表示该线程在对应延迟值上出现的次数( 注意是次数,不是延迟时间)。
Delay (μs) Thread 0 Thread 1 Thread 2 Thread 3 0 0 0 0 0 1 11 4 3 5 2 1511 3247 1081 809 ... ... ... ... ... 999 0 0 0 0
# Total: 000010000 000010000 000010000 000010000
每个线程总共执行了 10,000 次循环唤醒任务
# Min Latencies: 00001 00001 00001 00001
所有线程的最小延迟都是 1 微秒,非常快速地响应定时器唤醒请求。
# Avg Latencies: 00003 00002 00003 00002
每个线程平均延迟为 2或3 微秒。
# Max Latencies: 00020 00007 00008 00007
第 0 号线程出现了 20 微秒的最大延迟,其他线程最大延迟都在 7~8 微秒之间。
# Histogram Overflows: 00000 00000 00000 00000
# Histogram Overflow at cycle number:
# Thread 0:
# Thread 1:
# Thread 2:
# Thread 3:
所有线程都没有发生“直方图溢出”,没有超出1000微秒。后面是统计溢出是的情况,所以为空。
4、总结
这里使用的是树莓派官方的内核镜像,实验配置了线程优先级,锁定内寸页,但没有使用 PREEMPT_RT 实时内核,配置核隔离和关闭不必要的服务和软时钟中断源,对于实时内核来说还有一定优化空间。
在这样的测试环境下看测试结果,整体良好,最小延迟 1μs,最大延迟 20μs(0号核个别异常点),所有线程的最大延迟都较低,说明 Raspberry Pi 5在这个配置下具备较好的实时性表现。