1. 介绍

为了满足用户对系统实时性的需求,官方在 SDK 源码的内核基础上支持升级 Linux 到 RTLinux。 我们RTlinux支持有preempt和xenomai两个版本,下面以preempt版本来测试。

1.1. RTLinux 系统固件支持

支持RK3562、RK356X及RK3588等芯片平台,可前往对应机器版型下载固件页面下载实时固件。如需要源码请联系商务。

1.2. 测试实时效果

测试实时性能需要cyclictest,可以使用apt安装。

apt update
apt install rt-tests

1.2.1. 测试RTLinux的实时效果

使用stress或stress-ng模拟通用的压力场景,使CPU处于满负荷状态。

# 根据芯片核心数运行cpu压测线程、io压测线程及内存压测线程
stress --cpu 4 --io 4 --vm 4 --vm-bytes 256M --timeout 259200s &

执行以下命令测试每个核心实时响应延迟,将进行为期3天的测试,测试完成后的测试结果输出到output文件。

cyclictest -m -S -p99 -i1000 -h800 -D3d -q > output

我们执行以上操作分别在rk3568、rk3562及rk3588进行3天的延迟测试。其中rk3568和rk3562将CPU3从内核SMP平衡和调度算法中剔除,而rk3588将CPU6和CPU7从内核SMP平衡和调度算法中剔除,以便观察芯片最好的实时性能。

为了便于观察,我们将rk3568、rk3562及rk3588的测试结果转换成直方图和表,如下所示。 在本次测试中,RK3562的CPU2核心Max Latencies值最大,为152us,隔离CPU3核心(从内核SMP平衡和调度算法中剔除的核心)的Max Latencies值最小,为20us。 RK3568的CPU0核心的Max Latencies值最大,为135us,隔离CPU3核心的Max Latencies值最小,为18us。 RK3588的CPU0核心的Max Latencies值最大,为45us,隔离CPU7核心的Max Latencies值最小,为3us。

由此可见,在同芯片平台下隔离核心的实时性最好。所以尽量将我们的实时任务绑定到隔离核心运行,以获得最好的实时效果。

_images/rk3562_plot.png

Latencies \ Core CPU0 CPU1 CPU2 CPU3
Total 420738794 420738789 420738773 420738757
Min Latencies 00003 00003 00003 00002
Avg Latencies 00009 00008 000012 00003
Max Latencies 00074 00078 00152 00020

_images/rk3568_plot.png

Latencies \ Core CPU0 CPU1 CPU2 CPU3
Total 259200000 259199935 259199824 259199769
Min Latencies 00004 00003 00003 00003
Avg Latencies 000017 000015 000017 00004
Max Latencies 000135 000112 00107 00018

_images/rk3588_plot.png

Latencies \ Core CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
Total 259200000 259199978 259199943 259199926 259199914 259199930 259199871 259199898
Min Latencies 00003 00003 00003 00003 00001 00001 00001 00001
Avg Latencies 00007 00006 00006 00006 00003 00003 00001 00001
Max Latencies 00045 00037 00035 00033 00024 00020 00004 00003

1.2.1.1. 其他压力场景

不同场景的延迟测试结果不尽相同,为了尽可能接近我们的生产环境,可同时制作其他压力场景,如: 制造网络压力:

#使用iperf进行上下行同时测试,使网卡的发送和接收处于满负载状态
iperf -c 192.168.1.220 -p 8001 -f m -i100 -d -t 259200

制造gpu压力:

#无限地运行,从最后一个基准循环到第一个基准
glmark2-es2-wayland --run-forever

1.2.2. Cyclictest标准测试

threads选项(-t)用于指定Cyclictest在检测延迟时将使用的测量线程数。通常,在系统上的每个CPU上只运行一个测量线程是一个标准的测试方案。可以使用亲和性选项(-a)指定线程必须在其上执行的cpu。

这些选项对于最小化运行Cyclictest对观察到的系统的影响至关重要。在使用Cyclictest时,确保在任何给定时间只执行一个测量线程是很重要的。如果两个或多个Cyclictest线程的预期执行时间重叠,则Cyclictest的测量将受到其自己的测量线程所造成的延迟的影响。确保在给定的时间只执行一个测量线程的最好方法是在给定的CPU上只执行一个测量线程。

例如,如果要分析三个特定cpu的延迟,则指定应该使用这些cpu(使用-a选项),并指定应该使用三个测量线程(使用-t选项)。在这种情况下,为了最小化Cyclictest的开销,请确保收集度量数据的主Cyclictest线程没有运行在三个隔离的cpu之一上。主线程的关联性可以使用taskset程序设置,如下所述。

1.2.2.1. 在评估一组隔离的cpu上的延迟时,减小cyclictest的影响

在测量cpu子集上的延迟时,确保主Cyclictest线程正在未被评估的cpu上运行。例如,如果一个系统有两个CPU,并且正在评估CPU 0上的延迟,那么主Cyclictest线程应该固定在CPU 1上。Cyclictest的主线程不是实时的,但是如果它在被评估的CPU上执行,它可能会对延迟产生影响,因为会有额外的上下文切换。在启动Cyclictest之后,可以使用taskset命令将主线程限制为在cpu的某个子集上执行。例如,针对CPU1到CPU3的延时测试:

#CPU1到CPU3运行实时程序,主线运行在CPU0上
taskset -c 0 ./cyclictest -t3 -p99 -a 1-3

taskset程序还可以用于确保系统上运行的其他程序不会影响隔离CPU上的延迟。例如,启动程序top查看线程并固定到CPU 0上,使用下面的命令:

taskset --cpu 0 top -H -p PID
#top打开之后点击f键,光标移动到 P 选项,空格选中,然后点击 q建退出,便可查看到实时线程在哪些CPU上运行。

1.3. 提高实时策略

1.3.1. 抑制控制台消息及禁止内存过度使用

#可以使用内核参数quiet启动内核,或者启动之后抑制,如下:
echo 1 > /proc/sys/kernel/printk

#禁用内存过度使用以避免 Out-of-Memory Killer产生的延迟
echo 2 > /proc/sys/vm/overcommit_memory

1.3.2. 不使用桌面或者使用轻量级窗口管理器

为了更好的实时,我们不建议使用带桌面的系统,因为这将为CPU延迟带来很大的挑战。建议使用minimal ubuntu、自己的QT程序等。 356x的rt固件默认不使用桌面,而是使用窗口管理器weston,显示协议是Wayland。

1.3.2.1. 切换X11环境

如果你需要X11的环境,可手动切换到X11

sudo set_display_server x11
reboot
#sudo set_display_server weston 可再次切换回weston,重启生效
1.3.2.1.1. 使用openbox 窗口管理器启动

切换到X11环境默认使用桌面,如果需要使用轻量级的窗口管理器 在/etc/lightdm/lightdm.conf 指定ession使用openbox窗口管理器:

cat /etc/lightdm/lightdm.conf.d/20-autologin.conf 
[Seat:*]
user-session=openbox
autologin-user=firefly
1.3.2.1.2. 只运行自己的X11程序

若是不用登录管理器启动 X显示服务,可使用xinit手动启动Xorg显示服务。 执行xinit和startx时,它们将寻找~/.xinitrc做为shell脚本运行以启动客户端程序。 若是~/.xinitrc不存在,startx将运行默认值/etc/X11/xinit/xinitrc(默认的xinitrc启动一个Twm,xorg-xclock和Xterm环境)。

首先关闭lightdm服务

systemctl disable lightdm

然后使用startx启动自己的程序

startx chromium

也可修改默认startx指定的client 的xinitrc文件,默认的会运行Xorg

vim /etc/X11/xinit/xinitrc
-------------------------------------------------------------
#!/bin/sh
  
# /etc/X11/xinit/xinitrc
#
# global xinitrc file, used by all X sessions started by xinit (startx)

# invoke global X session script
#. /etc/X11/Xsession
#chromium --window-size=1920,1080
chromium --start-maximized  

1.3.3. 绑定核心

实时要求高的事件固定到某个核心上处理,系统及其它实时要求不高的事件集中到一个核心上处理。例如特定的中断,实时程序等事件可以用专门的核心为他们服务。

1.3.3.1. 任务绑定核心

rt应用可由特定核心处理,将rt应用绑定到cpu3

taskset -c 3 rt_task

1.3.3.2. 中断绑定核心

由于arm将所有外设中断全部由cpu0处理,对于重要的中断可以在系统启动之后将中断绑定到其他核心。 例如将eth0中断绑定到cpu2

root@firefly:~# cat /proc/interrupts | grep  eth0
 38:   28600296          0          0          0     GICv3  64 Level     eth0
 39:          0          0          0          0     GICv3  61 Level     eth0

root@firefly:~# cat /proc/irq/38/smp_affinity_list 
0-3

root@firefly:~# echo 2 > /proc/irq/38/smp_affinity_list

root@firefly:~# cat /proc/irq/38/smp_affinity_list 
2
root@firefly:~# cat /proc/interrupts | grep  eth0
 38:   29009292          0      52859          0     GICv3  64 Level     eth0
 39:          0          0          0          0     GICv3  61 Level     eth0

1.3.4. 使用smp+amp方案

对于实时要求更高的,可以使用amp方案,以达到更好的实时控制。 rk3568支持了amp(非对称多核架构),你可以定制某些核心跑定制的系统。 比如0~2核心跑kernel,3核心跑rt-thread等;支持 Linux(Kernel-4.19、rt-kernel-4.19)、 Baremetal(HAL)、RTOS(RT-Thread) 组合AMP构建形式,可任意搭配。 不同内核之间可以使用核间通信来进行信息交互。