一、简介:国产芯“能跑”还不够,“实时稳”才是硬道理
背景:能源、矿山、轨道交通等关键领域要求控制周期 ≤ 1 ms、抖动 ≤ 50 μs。飞腾平台虽自带 ARMv8 高性能核,但默认内核PREEMPT_NONE根本无法满足硬实时需求。
痛点:
系统偶发 200 μs 延迟 → 矿山皮带保护延迟 → 安全 PLC 报“Fault”。
驱动内存泄漏 → 连续运行 3 天重启 → 无人值守变电站被迫停机。
价值:掌握飞腾平台实时内核调试工具链,可定位延迟瓶颈、消除内存泄漏、验证调度正确性,让国产化方案真正“可用、敢用、好用”。
二、核心概念:5 个关键词先搞懂
| 关键词 | 一句话 | 飞腾平台注意 |
|---|---|---|
| PREEMPT_RT | Linux 实时补丁,将自旋锁变互斥锁、关中断段可抢占 | 需重新编译内核 |
| cyclictest | 测量中断→任务唤醒→实际调度的时间差 | ARMv8 下使用perf cycle时钟 |
| ftrace | 内核函数跟踪,可图形化 | 需打开CONFIG_FUNCTION_TRACER |
| perf | PMU 性能计数,查热点、Cache miss | 飞腾 PMU 驱动armv8_pmuv3 |
| kmemleak | 内存泄漏检测,类似 Valgrind 内核版 | 需CONFIG_DEBUG_KMEMLEAK |
三、环境准备:10 分钟搭好“飞腾调试工作台”
1. 硬件
FT-2000/4 工业板卡(4×A72,2.2 GHz)
串口线 1 根(115200)用于裸机日志
网线 1 根(千兆,NFS 加载调试符号更快)
2. 软件
| 组件 | 版本 | 获取方式 |
|---|
实时内核 | linux-5.15.y-rt53 | 飞腾官方仓库 https://gitee.com/phytium/embed-linux
交叉工具链 | gcc-linaro-11.3-2022.06-x86_64_aarch64-linux-gnu | 官网下载解压即可
调试工具 | rt-tests 2.5 + perf 5.15 + trace-cmd 3.1 | 源码编译,见下脚本
文件系统 | Ubuntu 20.04 arm64 rootfs | nfsroot 便于在线更新模块
3. 一键脚本:装工具链 + 编译 RT 内核
#!/bin/bash # setup_ft_env.sh set -e TOOLCHAIN=$HOME/phytium/gcc-linaro-11.3-2022.06-x86_64_aarch64-linux-gnu export ARCH=arm64 export CROSS_COMPILE=$TOOLCHAIN/bin/aarch64-linux-gnu- git clone -b v5.15-rt53 https://gitee.com/phytium/embed-linux.git cd embed-linux make phytium_defconfig ./scripts/config -e CONFIG_PREEMPT_RT ./scripts/config -e CONFIG_FUNCTION_TRACER ./scripts/config -e CONFIG_DEBUG_KMEMLEAK make -j$(nproc) Image dtbs modules make INSTALL_MOD_PATH=~/nfsroot modules_install输出文件:
arch/arm64/boot/Image→ 内核embed-linux/vmlinux→ 带符号 ELF,gdb 用
四、应用场景(300 字):矿山皮带运输综合保护系统
某大型露天矿皮带机长 4 km,带宽 1.6 m,设计运力 8000 t/h。沿线部署 300 只拉绳开关、80 只撕裂传感器、20 台高清摄像仪,全部接入飞腾 FT-2000/4 边缘控制器。系统要求:
控制周期 500 μs,任何传感器动作→停机命令≤1 ms;
7×24 h 连续运行,MTBF≥30000 h;
符合 GB/T 20438(等同 IEC 61508)SIL2 认证。
通过本文调试方法,团队将 cyclictest 最大抖动从 187 μs 降至 38 μs;kmemleak 提前发现网卡驱动 4 kB/h 泄漏;ftrace 定位到 USB 中断抢占调度路径过长,改用 GPIO 边沿触发后,延迟再降 15 μs。最终系统一次通过第三方认证,实现国产化替代。
五、实际案例与步骤:从“跑起来”到“测得准”
实验目录统一:~/ft-lab,所有脚本均放此处。
mkdir -p ~/ft-lab && cd ~/ft-lab5.1 实时延迟测量:cyclictest 飞腾版
目标:测量“中断→任务唤醒”时间,验证是否 < 50 μs。
# 1. 板端运行(nfsroot 已含 rt-tests) sudo cyclictest -p99 -i100 -d60s -Sp90 -m > cyclictest.log & # 2. 60 秒后查看 grep "Max" cyclictest.log典型输出:
T: 0 ( 1234) P:99 I:100 C: 600000 Min: 8 Act: 14 Avg: 16 Max: 38
Max=38 μs → 达标。
常见调优:
BIOS 关 Turbo、C-State;
内核启动参数加
nohz_full=2-3 isolcpus=2-3;将 cyclictest 线程绑核:
taskset -c 2 cyclictest ...
5.2 调度异常定位:ftrace 图形化
场景:偶发 200 μs 抖动,需找出哪段函数关闭中断过长。
# 板端执行 echo function > /sys/kernel/debug/tracing/current_tracer echo 1 > /sys/kernel/debug/tracing/options/function-trace echo *usb* > /sys/kernel/debug/tracing/set_ftrace_filter echo 1 > /sys/kernel/debug/tracing/tracing_on # 跑业务 30 s sleep 30 echo 0 > /sys/kernel/debug/tracing/tracing_on cat /sys/kernel/debug/tracing/trace > usb-trace.log把usb-trace.log拷贝到 PC:
trace-cmd report < usb-trace.log | kernelshark图形化结果可看到usb_hcd_irq占用 180 μs → 驱动频繁 kmalloc。改为预分配 DMA 描述符环后,抖动降至 35 μs。
5.3 内存泄漏狩猎:kmemleak
目标:连续运行 24 h,驱动无泄漏。
# 1. 打开 kmemleak echo scan > /sys/kernel/debug/kmemleak # 2. 24 小时后再次扫描 echo scan > /sys/kernel/debug/kmemleak cat /sys/kernel/debug/kmemleak > kmemleak.log若日志出现:
unreferenced object 0xffff800011234000 (size 4096): comm="irq/47-eth0", pid=123, jiffies=4292431 backtrace: [<00000000803d773c>] netdev_alloc_skb+0x3c/0x88 [<00000000802f1a10>] ftgmac_rx+0x198/0x2b0→ 网卡驱动每中断泄漏 4 kB,修复方法:使用napi_alloc_skb()并在napi_complete()后释放。
5.4 PMU 性能热点:perf
场景:CPU 占用 70%,需找热点函数。
# 板端采集 10 s sudo perf record -a -g -- sleep 10 sudo perf report > hot.log结果示例:
Overhead Symbol 42.30% memcpy 11.20% crc32_be→memcpy占比高,原因是应用层 64 Byte 小包频繁拷贝。改用mmap零拷贝后,CPU 降至 35%,留出更多余量给实时任务。
5.5 一键日常巡检脚本(可复制)
#!/bin/bash # daily_check.sh DATE=$(date +%F_%H-%M) LOGDIR=/var/log/ft-lab mkdir -p $LOGDIR echo "=== 1. cyclictest 10 s ===" > $LOGDIR/check-$DATE.log cyclictest -p99 -i100 -d10s -n | grep Max >> $LOGDIR/check-$DATE.log echo "=== 2. kmemleak scan ===" >> $LOGDIR/check-$DATE.log echo scan > /sys/kernel/debug/kmemleak cat /sys/kernel/debug/kmemleak | head -20 >> $LOGDIR/check-$DATE.log echo "=== 3. dmesg 错误 ===" >> $LOGDIR/check-$DATE.log dmesg | grep -i error | tail -10 >> $LOGDIR/check-$DATE.log echo "巡检完成,日志:$LOGDIR/check-$DATE.log"加入 crontab:
echo "0 * * * * /root/ft-lab/daily_check.sh" | crontab -六、常见问题与解答(FAQ)
| 问题 | 现象 | 解决 |
|---|---|---|
| cyclictest 报“Function not implemented” | 内核未开 CONFIG_PREEMPT_RT | 重新编译 RT 内核 |
| ftrace 无输出 | current_tracer 为空 | 先echo function > current_tracer再开 trace |
| kmemleak 一直“scanning” | 内存大、扫描慢 | 加echo offline > /sys/kernel/debug/kmemleak离线扫描 |
| perf 报“Permission denied” | 未开 PMU 驱动 | 确认内核配置CONFIG_ARM_PMU=y |
| jitter 偶尔 > 100 μs | 超线程/电源管理未关 | BIOS 关闭 Turbo、C-State,加 isolcpus |
七、实践建议与最佳实践
“两步法”定位抖动
先跑 cyclictest 找最大值 → 再用 ftrace 抓该时段函数流,避免海量日志。绑定核策略
实时任务绑isolcpus核;中断亲和性把非实时 IRQ 赶到其他核。符号常驻
开启CONFIG_KALLSYMS_ALL=y,gdb/perf 才能看到函数名。版本锁定
工具链、内核、rootfs 哈希写入《平台配置清单》,任何升级走 MR。持续基线
每晚 CI 自动跑 cyclictest + kmemleak,超阈值自动发邮件。用 Git 管理追踪
perf 报告、trace 图统一放到docs/perf/目录,历史可比对。
八、总结:一张脑图带走全部要点
飞腾实时 Linux 调试 ├─ 延迟:cyclictest + isolcpus + nohz_full ├─ 函数:ftrace + kernelshark 图形化 ├─ 内存:kmemleak 扫泄漏 ├─ 热点:perf PMU 找瓶颈 └─ 巡检:daily_check.sh 自动落盘掌握以上工具链,你就拥有了国产飞腾芯的“实时显微镜”:
让矿山皮带保护延迟 < 1 ms,
让驱动内存泄漏提前现形,
让 SIL2 认证有数据可循。
立刻复制本文脚本到你的飞腾板卡,跑一遍cyclictest,再打开kernelshark——国产芯+实时Linux的“稳如磐石”,从调试开始!