来自 Industrial-Control SIG的郭皓
将在 openEuler Developer Day 2022 分享
《openEuler在嵌入式和实时性方面的思考与实践》
欢迎大家观看直播
openEuler 22.03 LTS 版本新增了 Preempt_RT 内核实时补丁,提供软实时特性。该特性由 Industrial-Control SIG 引入,并得到 Kernel SIG、Embedded SIG 和 Yocto SIG 配合与支持,已经被集成到openEuler 22.03 LTS Server 和 openEuler 22.03 LTS Embedded 中。
什么是实时系统
实时系统的典型定义如下:“所谓实时系统,就是系统中计算结果的正确性不仅取决于计算逻辑的正确性,还取决于产生结果的时间。如果完成时间不符合要求,则可以认为系统发生了问题。”也就是说,不管实时应用程序执行的是何种任务,它不仅需要正确执行该任务而且必须及时完成。当前,Preempt_RT 维护者 Thomas Gleixner 给出的“实时”含义是:它和指定的一样快。
Linux 作为一种通用操作系统,随着时间的推移,在功能和时序行为方面一直在发展,以便适合许多其他更具挑战性的场景;尤其是实时系统对 Linux 的实时性改造一直从未停止过。
对 Linux 进行实时性改造,通常可从两个大的方向来着手。一个方向是从 Linux 内核内部开始,直接修改其内核源代码,其典型代表是 Preempt_RT 实时补丁;另一个方向则是从 Linux 内核的外围开始,实现一个与 Linux 内核共存的实时内核,即采用双内核方法,其典型实现为 RTAI/Linux,即现在的 Xenomai。
因为 Xenomai 实时内核与 Linux 内核共存,Xenomai 实时内核小而精巧,能够很好地控制其中的代码质量。Xenomai 实时内核完成了基本的硬件抽象层、任务调度管理和进程间通信管理模块等,能够满足一些硬实时系统的需求。然而,其上的实时应用通常分为实时和非实时两部分来完成 ,实时部分必须使用 Xenomai 提供的特有的 API;非实时部分则可以使用 Linux 提供的系统调用。与 Preempt_RT 实时编程相比,Xenomai 编程实现更为困难,软件移植难度更大。
与双内核机制方案相比,Preempt_RT 实时补丁最大的优势在于它遵循 POSIX 标准,使用该补丁的实时系统应用程序和驱动程序与非实时系统的应用和驱动程序差异很小。因此,在使用该补丁的平台上做相应的开发比双内核机制的方案更容易。另外,该补丁与硬件平台相关性小,可移植性高。由于 Linux 内核过于庞大,有着较多关中断、关抢占代码,加上复杂的内存管理、调度器代码逻辑等众多不确定性因素,使得 Preempt_RT 虽然具有较好的软实时性,但在硬实时性方面有所欠缺。
什么是 Preempt_RT
Preempt_RT 补丁开发始于 2005 年。之后由德国 OSADL 组织赞助,Ingo Molnar、Thomas Gleixner 和 Steven Rostedt 三人共同发起,旨在将 Linux 内核的最大线程切换延迟从无限制的毫秒数降低到数十微秒的有界值。2016 年以后成为 Linux 基金会下属合作项目。目前 Preempt_RT 的赞助者来自 ARM、BMW、CIP、ELISA、Intel、National Instruments、OSADL、RedHat 和 Texas Instruments 等。经过 Preempt_RT 和 Linux 内核工程师在抢占、实时性方面的努力,Linux 内核的抢占延迟降低了几个数量级,使其能够与商业实时操作系统竞争。业界知名的 MontaVista Linux、WindRiver Linux、TimeSys Linux 都有 RT 补丁的身影。像 RTJVM、RTKVM、RTDocker、RTAndroid 等曾经出现过的 Preempt_RT 衍生用例,响应速度都有着不同程度的提升。
多年来,该补丁的许多部分已被纳入主线 Linux,包括高分辨率计时器(2.6.16)、优先级继承(2.6.18)、可抢占的 RCU(2.6.25)、内核互斥量和线程中断处理程序(2.6.30)、完全 Tickless 机制(3.10)、DL 调度器(EDF 调度算法)(3.14)、实时抢占锁(5.15)。然而,该补丁的核心部分仍然在主线之外。从近几年的 Preempt_RT 补丁来看,当前的主要工作不是开发新功能,而是专注于增量式引入主线和特定架构的支持。
当前 openEuler 22.03 LTS 主线内核版本为 Linux Kernel 5.10,有 180 把锁无法抢占,其中 8 把锁在 RT 补丁中强制修改成无法抢占。在最新的 5.17 内核中,Preempt_RT 补丁大小为 265KB,有 189 把锁仍然无法抢占,RT 补丁不再强制修改锁为无法抢占。
当前 Preempt_RT 主要特性
- 临界区可抢占
- 中断处理程序可抢占
- 关中断代码序列可抢占
- 带有优先级继承机制的内核自旋锁和信号量
- 线程化处理 RCU
- 降低延迟措施
部署方法
二进制部署
二进制部署可以安装 openEuler 22.03 LTS 官方源中 rpm 包,需要 root 权限,命令如下:
# yum install kernel-rt
完成安装后重启设备,在 GRUB 引导界面选择 Preempt_RT 内核openEuler (5.10.0-60.18.0.rt62.52.oe2203.aarch64) 22.03 LTS
即可。启动后查看内核,即完成 openEuler 22.03 LTS Preempt_RT 二进制部署。
# uname -r5.10.0-60.18.0.rt62.52.oe2203.aarch64
获取源码
openEuler 22.03 LTS kernel-rt
源码可以直接从官方源获取,查询命令如下:
# yum search kernel-rt...kernel-rt.src : Linux Kernel
若源里包含 kernel-rt
源码,则可使用如下方式下载并安装:
# yumdownloader --source kernel-rt.src# rpm -ivh kernel-rt-5.10.0-60.18.0.rt62.52.oe2203.src.rpm && cd ~/rpmbuild
源码目录树如下:
# tree.├── SOURCES│ ├── cpupower.config│ ├── cpupower.service│ ├── extra_certificates│ ├── kernel.tar.gz│ ├── mkgrub-menu-aarch64.sh│ ├── patch-5.10.0-60.10.0-rt62_openeuler_defconfig.patch│ ├── patch-5.10.0-60.10.0-rt62.patch│ ├── pubring.gpg│ ├── sign-modules│ └── x509.genkey└── SPECS └── kernel-rt.spec
文件 | 说明 |
---|---|
kernel.tar.gz | 内核源码 |
patch-5.10.0-60.10.0-rt62_openeuler_defconfig.patch | openeuler_defconfig 文件补丁 |
patch-5.10.0-60.10.0-rt62.patch | Preempt_RT 补丁 |
kernel-rt.spec | Preempt_RT 内核 spec 文件 |
源码部署
源码获取后,复制以下文件到自定义目录:
# lltotal 186M-rw-r--r--. 1 root root 185M Apr 2 14:27 kernel.tar.gz-rw-r--r--. 1 root root 4.5K Apr 2 14:27 patch-5.10.0-60.10.0-rt62_openeuler_defconfig.patch-rw-r--r--. 1 root root 773K Apr 2 14:27 patch-5.10.0-60.10.0-rt62.patch
补丁合入步骤如下:
# tar -xzf kernel.tar.gz && cd kernel# patch -p1 < ../patch-5.10.0-60.10.0-rt62.patch# patch -p1 < ../patch-5.10.0-60.10.0-rt62_openeuler_defconfig.patch
源码编译安装:
# make openeuler_defconfig && make -j`nproc`# make modules_install && make install# grub2-mkconfig -o $GRUB_CONFIG_PATH
嵌入式系统部署方法
嵌入式部署 Preempt_RT 方法参见:
https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html
实时性能测试
缩略语 | 英文全名 | 说明 |
---|---|---|
RT 内核 | Realtime kernel | 实时内核,本文指 openEuler 22.03 LTS 发布的kernel-rt 内核 |
非 RT 内核 | / | 非实时内核,实时内核,本文指 openEuler 22.03 LTS 发布的kernel 内核 |
测试环境
版本名称 | 来源 |
---|---|
openEuler 22.03 LTS kernel 内核 |
openEuler 22.03 LTS 官方源 |
openEuler 22.03 LTS kernel-rt 内核 |
openEuler 22.03 LTS 官方源 |
硬件型号 | 硬件配置信息 | 备注 |
---|---|---|
飞腾 D2000 | CPU:8 核 内存:8GB 存储设备:SSD | 台式机 |
树莓派 4B | CPU:Cortex-A72 * 4 内存:8GB 存储设备:SanDisk Ultra 16GB micro SD | 开发板 |
飞腾 2000 | CPU:4 核 内存:16GB 存储设备:SSD | 台式机 |
测试软件 | 功能 | 软件版本 |
---|---|---|
rt-test(cyclictest) | 通过 cyclictest 工具,每项测试 1000 万次,输出平均延迟(Avg)和最大延迟(MAX) | 1.00 |
stress | 压力测试工具,用于模拟测试 CPU 负载,内存负载,IO 负载等 | 1.0.4 |
iperf3 | 网络测试工具,用于模拟测试网络负载 | 3.6 |
memtester | 内存测试工具,用于模拟测试内存负载 | 4.5.1 |
shell 脚本 | 用于轮询测试,测试信息的收集整理 | — |
测试结果
基于上述硬件测试环境,在 CPU 隔离、空负载、CPU 负载、内存负载、IO 负载和网卡负载等不同条件下的测试数据:
「归纳如下:」
- 通过表 6 数据可以判断,在五种负载情况下并且 CPU 不隔离,RT 内核比非 RT 内核实时性要强。非 RT 内核与 RT 内核在 CPU 不隔离情况下,五种负载对应峰值的比值如表 7(比值数据越大表明非 RT 内核实时性越差):
平台 | 空负载 | CPU 负载 | 内存负载 | IO 负载 | 网卡负载 |
---|---|---|---|---|---|
飞腾 D2000 | 22.7 | 117.1 | 51.0 | 184.6 | 2.9 |
树莓派 4B | 3.6 | 2.9 | 4.3 | 0.8 | 1.5 |
飞腾 2000 | 5.4 | 4.3 | 5.3 | 34.7 | 10.6 |
「以上数据表明,RT 内核的峰值延迟普遍要优于非 RT 内核。」
- 结合四种设备的峰值延迟来看,CPU 负载对实时性影响一般小于 IO 和内存负载,而网卡负载影响最小。四种设备在两种内核下,CPU、内存、IO 和网卡负载与空负载比值如表 8(比值越小越稳定):
平台 | CPU 负载 | 内存负载 | IO 负载 | 网卡负载 |
---|---|---|---|---|
飞腾 D2000(非 RT 内核) | 5.2 | 43.1 | 212.8 | 2.7 |
树莓派 4B(非 RT 内核) | 0.8 | 2.7 | 1.0 | 0.7 |
飞腾 2000(非 RT 内核) | 0.8 | 18 | 26.8 | 1.9 |
飞腾 D2000(RT 内核) | 1.0 | 19.2 | 26.2 | 20.6 |
树莓派 4B(RT 内核) | 0.9 | 1.2 | 4.2 | 1.0 |
飞腾 2000(RT 内核) | 1.0 | 2.2 | 4.5 | 1.7 |
「表 8 各项数据表明,RT 内核在负载情况下,实时性较为稳定。」
「为确保 Cyclictest 测试的有效性,经过飞腾 2000 平台空载测试 2 天,最大延迟为 58 微秒。」
实时性对系统影响测试
测试环境
版本名称 | 来源 |
---|---|
openEuler 22.03 LTS kernel 内核 |
openEuler 22.03 LTS 官方源 |
openEuler 22.03 LTS kernel-rt 内核 |
openEuler 22.03 LTS 官方源 |
硬件型号 | 硬件配置信息 | 备注 |
---|---|---|
飞腾 D2000 | CPU:8 核 内存:16GB 存储设备:SSD | 台式机 |
飞腾 2000/4 | CPU:4 核 内存:16GB 存储设备:SSD | 台式机 |
测试软件 | 功能 | 版本 |
---|---|---|
unixbench | 系统的基准测试工具,可用于测试 CPU、内存、磁盘等。测试结果与硬件、系统、开发库、编译器等相关。 | 5.1.3 |
lmbench | 是一套简易可移植的,符合 ANSI/C 标准为 UNIX/POSIX 而制定的微型测评工具。一般来说,它衡量两个关键特征:反应时间和带宽。Lmbench 旨在使系统开发者深入了解关键操作的基础成本。 | 3alpha4 |
rt-test(cyclictest) | 通过 cyclictest 工具,每项测试 1000 万次,输出平均延迟(Avg)和最大延迟(MAX) | 1.00 |
测试结果
- 飞腾 D2000 平台 unixbench 测试结果
使用unixbench
单个任务测试非 RT 内核空负载、RT 内核空负载、RT 内核负载 cyclictest(cyclictest -m -h 100 -q -i100 -t 1 -p 99 -n),三种状态详细测试结果如下(表中“RT/非 RT”、“RT 负载/非 RT”为百分比值,数值越大说明 RT 内核性能越好):
测试项 | 非 RT 内核 | RT 内核 | RT 内核负载 | RT/非 RT | RT 负载/非 RT |
---|---|---|---|---|---|
Dhrystone 2 using register variables | 24920250.9 | 24994936.3 | 25463306.6 | 100.30% | 102.18% |
Double-Precision Whetstone | 4043.3 | 4042.8 | 4042.9 | 99.99% | 99.99% |
Execl Throughput | 2700.1 | 2112.1 | 2109.6 | 78.22% | 78.13% |
File Copy 1024 bufsize 2000 maxblock | 437294.1 | 307416.2 | 303652.3 | 70.30% | 69.44% |
File Copy 256 bufsize 500 maxblocks | 122072.4 | 88889.0 | 86090.9 | 72.82% | 70.52% |
File Copy 4096 bufsize 8000 maxblocks | 995255.5 | 809771.5 | 774228.3 | 81.36% | 77.79% |
Pipe Throughput | 612119.9 | 487314.9 | 482060.0 | 79.61% | 78.75% |
Pipe-based Context Switching | 79151.2 | 65953.5 | 65399.0 | 83.33% | 82.63% |
Process Creation | 5098.4 | 3481.7 | 3367.9 | 68.29% | 66.06% |
Shell Scripts (1 concurrent) | 3907.2 | 3311.8 | 3264.1 | 84.76% | 83.54% |
Shell Scripts (8 concurrent) | 1724.2 | 1199.9 | 1187.6 | 69.59% | 68.88% |
System Call Overhead | 478285.9 | 436596.3 | 434507.4 | 91.28% | 90.85% |
「System Benchmarks Index Score」 | 「773.4」 | 「626.4」 | 「618.5」 | 「80.99%」 | 「79.97%」 |
使用unixbench
多任务测试非 RT 内核空负载、RT 内核空负载、RT 内核负载 cyclictest(cyclictest -m -h 100 -q -i100 -t 1 -p 99 -n),三种状态详细测试结果如下(表中“RT/非 RT”、“RT 负载/非 RT”为百分比值,数值越大说明 RT 内核性能越好):
测试项 | 非 RT 内核 | RT 内核 | RT 内核负载 | RT/非 RT | RT 负载/非 RT |
---|---|---|---|---|---|
Dhrystone 2 using register variables | 199461755.8 | 199159490.6 | 195978301.9 | 99.85% | 98.25% |
Double-Precision Whetstone | 32216.4 | 32308.6 | 32094.1 | 100.29% | 99.62% |
Execl Throughput | 14832.9 | 9786.4 | 9375.0 | 65.98% | 63.20% |
File Copy 1024 bufsize 2000 maxblock | 924225.9 | 107564.5 | 104520.3 | 11.64% | 11.31% |
File Copy 256 bufsize 500 maxblocks | 253687.9 | 27474.4 | 26157.9 | 10.83% | 10.31% |
File Copy 4096 bufsize 8000 maxblocks | 2523753.4 | 415702.5 | 395431.5 | 16.47% | 15.67% |
Pipe Throughput | 4848867.9 | 3771186.3 | 3822723.4 | 77.77% | 78.84% |
Pipe-based Context Switching | 657475.9 | 526984.6 | 522867.1 | 80.15% | 79.53% |
Process Creation | 29117.5 | 11881.7 | 11580.0 | 40.81% | 39.77% |
Shell Scripts (1 concurrent) | 17309.7 | 8265.0 | 8199.6 | 47.75% | 47.37% |
Shell Scripts (8 concurrent) | 2308.1 | 957.1 | 937.3 | 41.47% | 40.61% |
System Call Overhead | 2928882.1 | 2765649.3 | 2744875.5 | 94.43% | 93.72% |
「System Benchmarks Index Score」 | 「3406.4」 | 「1525.8」 | 「1494.4」 | 「44.79%」 | 「43.87%」 |
-
飞腾 D2000 平台 lmbench 测试结果
使用
lmbench
测试非 RT 内核空负载、RT 内核空负载、RT 内核负载 cyclictest(cyclictest -m -h 100 -q -i100 -t 1 -p 99 -n),三种状态详细,测试十次取平均值,结果如下:表14:多任务Lmbench测试结果 -
飞腾 2000 平台测试结果
飞腾 2000 平台测试结果与飞腾 D2000 平台测试结果相似度较高,具体数据不在此处列出。
测试结论
「Preempt_RT 补丁可以有效提高系统实时性,且在多种负载场景下,实时性表现较为稳定。」
「Preempt_RT 补丁对本地通讯吞吐率有一定影响,主要提现为管道读写、文件拷贝,对系统调用延迟影响大多在 2 微秒以内。」
后续工作
-
跟随内核主线发布、维护 Preempt_RT 补丁
-
研发实时性性能分析工具
-
提升实时性
-
提升吞吐率
-
引入 RTLA、RTSL 机制等
主要参与者
特别感谢 Kernel SIG 组XieXiuQi、zhengzengkai,Embedded SIG 组wanming-hu,树莓派 SIG 组woqidaideshi,QA SIG 组suhang给予我们的帮助。
姓名 | Gitee ID | 邮箱 |
---|---|---|
郭皓 | guohaocs2c | guohao@kylinos.cn |
马玉昆 | kylin-mayukun | mayukun@kylinos.cn |
张远航 | zhangyh1992 | zhangyuanhang@kylinos.cn |