为助力开发者高效开展创龙科技研发评估板的 Linux-RT 应用开发,本文先对比分析系统实时性,再测试不同 CPU 状态下 Linux-RT 性能,同时提供两类典型开发案例,详解测试流程、编译方法及核心代码,帮助开发者掌握 Linux-RT 系统应用开发要点,保障评估板实时性应用稳定实现。
主要通过Cyclictest延迟检测工具,以及基于Linux-RT的应用程序评估Linux-RT系统的实时性,适用开发环境如下:
Windows开发环境:Windows 7 64bit、Windows 10 64bit
开发环境:VMware16.2.5、Ubuntu20.04.6 64bit
U-Boot:U-Boot-2017.09
Kernel:Linux-RT-5.10.160
LinuxSDK:LinuxSDK-[版本号](基于rk3588_linux_release_v1.2.1_20230720)
我司默认使用的是Linux内核,同时提供了Linux-RT内核位于产品资料“4-软件资料\Debian\Kernel\image\linux-5.10.160-[版本号]-[Git系列号]”目录下。请按照如下方法替换为Linux-RT内核。
将Linux-RT内核镜像boot-rt.img拷贝至评估板文件系统任意目录下。执行如下命令,替换内核镜像至系统启动卡,评估板重启生效。
备注:mmcblk1p3为系统启动卡对应的设备节点,如需固化至eMMC,请将设备节点修改为mmcblk0p3。
Target# dd if=boot-rt.img of=/dev/mmcblk1p3
Target# sync
Target# reboot
我司提供的Linux-RT内核应用了开源的RT PREEMPT机制进行补丁。PREEMPT_RT补丁的关键是最小化不可抢占的内核代码量,同时最小化必须更改的代码量,以便提供这种附加的可抢占性。Linux-RT内核增加PREEMPT_RT补丁后,增加了系统响应的确定性和实时性,但是代价是CPU性能降低。
Linux-RT内核与普通Linux内核相比,几个主要的相同之处是:
Linux-RT内核与普通Linux内核在常规编程方式上的几个主要不同之处是:
本章节主要介绍使用Cyclictest延迟检测工具测试Linux系统实时性的方法。Cyclictest是rt-tests测试套件下的一个测试工具,也是rt-tests下使用最广泛的测试工具,一般主要用来测试内核的延迟,从而判断内核的实时性。
Cyclictest常用于实时系统的基准测试,是评估实时系统相对性能的最常用工具之一。Cyclictest反复测量并精确统计线程的实际唤醒时间,以提供有关系统的延迟信息。它可测量由硬件、固件和操作系统引起的实时系统的延迟。
为了测量延迟,Cyclictest运行一个非实时主线程(调度类SCHED_OTHER),该线程以定义的实时优先级(调度类SCHED_FIFO)启动定义数量的测量线程。测量线程周期性地被一个到期的计时器(循环报警)所定义的间隔唤醒,随后计算有效唤醒时间,并通过共享内存将其传递给主线程。主线程统计延迟值并打印最小、最大和平均延迟时间。
参考链接:https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/cyclictest/start?s[]=cyclictest。
本次测试结合Iperf和Cyclictest工具,对比测试基于Linux-RT-5.10.160内核和Linux-5.10.160内核的系统实时性能。此处使用Iperf工具不断触发系统中断,提高中断处理负载,以便更好测试系统实时特性。
在Ubuntu执行如下命令查看IP地址,并以服务器模式启动Iperf测试。
Host# ifconfig
Host# iperf3 -s
分别使用Linux-RT-5.10.160内核和Linux-5.10.160内核启动评估板,执行如下命令以客户端模式启动Iperf,并连接至服务器端(Ubuntu系统)。"192.168.13.8"为Ubuntu的IP地址,"-t3600"设置测试时间为3600秒,"&"表示让程序在后台运行。
Target# iperf3 -c 192.168.13.8 -d -t3600 > /dev/null 2>&1 &
评估板文件系统默认已提供Cyclictest工具,进入评估板文件系统,执行如下命令使用Cyclictest工具测试系统实时性。
Target# stress --cpu 8 --io 8 --vm 8 --vm-bytes 64 --timeout 620s &
Target# cyclictest -t5 -p98 -m -D10m
对比测试数据,可看到基于Linux-RT-5.10.160内核的系统的延迟更加稳定,平均延迟、最大延迟更低,系统实时性更佳。
Cyclictest命令参数解析可执行"cyclictest --help"查看,如下图所示。
本次测试分别在CPU空载、满负荷(运行stress压力测试工具)、隔离CPU核心的情况下,对比评估Linux-RT内核的系统实时性。
评估板上电启动,进入评估板文件系统执行如下命令,修改内核printk日志等级,避免内核打印信息影响实时测试。
Target# echo 1 > /proc/sys/kernel/printk
调整内存分配策略为“1”,禁止内存过度使用。避免出现OOM(Out-of-Memory) Killer攻击某些进程而产生延迟,影响测试结果。
Target# echo 1 > /proc/sys/vm/overcommit_memory
执行如下命令,基于CPU空载状况下测试系统的实时性。测试指令需运行24小时,请保持评估板长时间稳定工作,测试完成后将生成统计结果no_load_output文件。
Target# cyclictest -m -Sp99 -i1000 -h800 -D24h -q > no_load_output
参数解析:
-m:锁定当前和将来的内存分配;
-S:采用标准SMP测试;
-p:设置线程优先级;
-i:设置线程的基本间隔;
-h:运行后将延迟直方图转储至标准输出,亦可指定要跟踪的最大延时时间(以微秒为单位);
-D:指定测试运行时长,附加m(分钟)、h(小时)、d(天)指定;
-q:运行时不打印相关信息;
评估板上电启动,进入评估板文件系统执行如下命令,修改内核printk日志等级,避免内核打印信息影响实时测试。
Target# echo 1 > /proc/sys/kernel/printk
调整内存分配策略为“1”,禁止内存过度使用。避免出现OOM(Out-of-Memory) Killer攻击某些进程而产生延迟,影响测试结果。
Target# echo 1 > /proc/sys/vm/overcommit_memory
执行如下命令,运行stress压力测试工具,使得CPU处于满负荷状态。再使用cyclictest工具测试CPU满负荷状态下的系统实时性能。测试指令需运行24小时,请保持评估板长时间稳定工作,测试完成后将生成统计结果overload_output文件。
Target# stress --cpu 8 --io 8 --vm 8 --vm-bytes 64 --timeout 86400s &
Target# cyclictest -m -Sp99 -i1000 -h800 -D24h -q > overload_output
参数解析:
--cpu:指定压力测试的进程个数;
--io:指定I/O测试的进程个数;
--vm:指定内存测试的进程个数;
--vm-bytes:指定每个内存测试进程中分配内存的大小;
--timeout:指定测试时长;
本次测试以隔离CPU3核心为例,通过降低系统上所运行的其他进程对隔离CPU3产生的延迟影响,确保CPU3进程的正常运行,进而评估Linux-RT内核的系统实时性。
评估板上电启动前长按"Ctrl + C"进入U-Boot命令行模式,执行如下命令,修改环境变量,隔离CPU3核心。
U-Boot# setenv bootargs "storagemedia=emmc androidboot.storagemedia=emmc androidboot.mode=normal isolcpus=3"
U-Boot# saveenv
U-Boot# reset
进入评估板文件系统,执行如下命令,查看环境变量是否设置成功。
Target# cat /proc/cmdline
执行如下命令,修改内核printk日志等级,避免内核打印信息影响实时测试。
Target# echo 1 > /proc/sys/kernel/printk
调整内存分配策略为“1”,禁用内存过度使用。避免出现OOM(Out-of-Memory) Killer攻击某些进程而产生延迟,影响测试结果。
Target# echo 1 > /proc/sys/vm/overcommit_memory
执行如下命令,运行stress压力测试工具,使得CPU处于满负荷状态。再使用taskset工具将cyclictest测试程序运行在CPU3核心,测试CPU3核心满负荷状态下的系统实时性能。测试指令需运行24小时,请保持评估板长时间稳定工作,测试完成后将生成统计结果iso_overload_output文件。
Target# stress --cpu 8 --io 8 --vm 8 --vm-bytes 64 --timeout 86400s &
Target# taskset -c 0-7 cyclictest -m -Sp99 -i1000 -h800 -D24h -q > iso_overload_output
我司已提供脚本文件get_histogram.sh用于绘制统计结果直方图,位于产品资料“4-软件资料\Demo\linux-rt-demos\Cyclictest\bin\”目录下,请将该脚本文件拷贝至Ubuntu工作目录下。
执行如下命令,赋予get_histogram.sh脚本可执行权限。
Host# chmod a+x get_histogram.sh
在Ubuntu系统执行如下命令,安装gnuplot工具。
Host# sudo apt-get install gnuplot -y
请将CPU空载状态下的统计结果no_load_output文件拷贝至Windows工作目录,使用Windows文本工具打开该文件并拖动至文件末尾,可查看Linux系统每个核心(CPU0~CPU7)的最小延迟(Min Latencies)、平均延迟(Avg Latencies)、最大延迟(Max Latencies)统计结果。
请将CPU空载状态下的统计结果no_load_output文件拷贝至Ubuntu,存放在get_histogram.sh同一目录下。
执行如下命令,拷贝并修改CPU空载状态下的统计结果文件名为output,并生成直方图文件plot.png,请将其拷贝至Windows下打开。
备注:满负荷状态统计结果文件overload_output与隔离CPU核心状态统计结果文件iso_overload_output亦需将文件名修改为output方可生成直方图文件plot.png。
Host# cp no_load_output output
Host# ./get_histogram.sh
根据统计结果no_load_output文件数据以及结合直方图,可得主要数据如下表。本次测试中,CPU1核心Max Latencies值最大,为54us,CPU7核心的Max Latencies值最小,为16us。
备注:
1.CPU满负荷状态
参考如上方法,分析CPU满负荷状态下的统计结果如下所示。本次测试中,CPU0核心Max Latencies值最大,为59us,CPU5、CPU7核心的Max Latencies值最小,为25us。
2.隔离CPU核心状态
参考如上方法,分析隔离CPU核心状态下的统计结果如下所示。本次测试中,CPU0、CPU1核心Max Latencies值最大,为59us,隔离CPU3核心的Max Latencies值相比CPU空载状态、CPU满负荷状态时CPU3核心的Max Latencies值最小,为18us。
根据CPU空载、CPU满负荷、隔离CPU核心三种状态的测试结果可知:当程序指定至隔离的CPU3核心上运行时,Debian系统延迟降低,可有效提高系统实时性。故推荐对实时性要求较高的程序(功能)指定至隔离的CPU核心运行。
通过创建一个基本的实时线程,在线程内触发LED的电平翻转,同时程序统计实时线程的调度延时,并通过示波器测出LED电平两次翻转的时间间隔。由于程序默认以最高优先级运行,为避免CPU资源被程序完全占用导致系统被挂起,因此在程序中增加100us的延时。程序原理大致如下:
本次测试以隔离CPU4核心为例进行演示,评估板上电前长按"Ctrl + C"进入U-Boot命令行模式,修改环境变量,隔离CPU4核心,保存环境变量后重启评估板。
U-Boot# setenv bootargs "storagemedia=emmc androidboot.storagemedia=emmc androidboot.mode=normal isolcpus=4"
U-Boot# saveenv
U-Boot# reset
进入评估板文件系统,执行如下命令,确认已正确隔离CPU。
Target# cat /proc/cmdline
将案例bin目录下的可执行文件拷贝至评估板文件系统,并执行如下命令运行测试程序,再按"Ctrl + C"退出测试,串口终端将打印程序统计的延迟数据,如下图所示。
Target# taskset -c 4 ./rt_gpio_ctrl
同时使用示波器捕捉LED两次电平翻转之间的间隔,即可得到线程调度的延迟,测试点为R62电阻一端。
本次测得电平翻转周期为∆x = 104us,如下图所示。由于程序中默认增加了100us的时间延时,因此实际延时应为:104us - 100us = 4us,与程序统计打印的Latency results平均值相近。
将产品资料“4-软件资料\Demo\linux-rt-demos\rt_gpio_ctrl\src\”案例源码拷贝至Ubuntu。进入案例源码目录,执行如下命令,编译案例生成可执行文件。
Host# export PATH=/home/tronlong/RK3588/rk3588_linux_release_v1.2.1/extra-tools/gcc-linaro-10.2.1-2021.01-x86_64_aarch64-linux-gnu/bin:$PATH
Host# make CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++
(1)创建实时任务,具体操作包括内存锁定、线程堆栈内存设置、调度策略和优先级配置等。
(2)在线程中打开LED文件节点,并对LED状态进行翻转。
(3)统计调度时间延时情况。
由于篇幅过长等原因,部分内容均不逐一展示,如需获取完整版详细资料,请关注创龙科技微信公众号或官网,或者评论区留言,感谢您的支持!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。