目录

edge-diag:基于 eBPF 的系统异常观测与根因定位工具

edge-diag 是面向联想/openKylin eBPF 赛题开发的轻量级系统异常诊断工具。 项目基于 libbpf CO-RE,在内核态进行有界聚合,在用户态完成多维指标关联、 规则诊断、证据链生成以及 JSON、YAML、Markdown 结构化报告输出。

当前版本覆盖赛题要求的全部五类场景:

  • CPU 异常占用、调度延迟和上下文切换异常;
  • 块设备 I/O 延迟抖动、队列拥堵和错误;
  • 内存缺页、回收抖动和 OOM 风险;
  • futex 锁竞争和长时间等待;
  • 高频、高耗时或高错误率系统调用热点。

一、原生验证结论

最终冻结版本已在以下环境完成真实编译、BPF 加载和场景测试:

项目 验证结果
操作系统 openKylin 2.0 SP2
架构 x86_64
内核 6.6.0-19-generic
eBPF 工具链 Clang 17、libbpf 1.3、bpftool 7.3
场景覆盖 CPU、I/O、内存/OOM、锁、系统调用,共五类
准确率测试 30 个窗口,受控用例 macro-F1 为 1.0
空闲 CPU 开销 三轮 30 秒测试中位数为单核 0.45%
用户态最大 RSS 中位数 17,796 KiB
I/O 吞吐影响 三轮 fio 配对测试中位数 -2.18%
读 P99 影响 三轮 fio 配对测试中位数 +4.57%

二、五分钟快速验证

1. 安装依赖

./scripts/install_deps.sh

如果 openKylin 软件源没有提供 bpftool,脚本会下载固定版本的官方静态 bpftool,并验证发布方提供的 SHA-256。

2. 编译和回归测试

make check

make check 会完成 CO-RE BPF 对象编译、libbpf skeleton 生成、用户态程序 编译、规则回归测试,以及 JSON、YAML、Markdown 输出校验。

3. 检查运行条件

sudo ./build/edge-diag doctor

4. 启动真实观测

sudo ./build/edge-diag start \
  --duration 10 \
  --format json \
  --output output/judge-report.json

python3 scripts/validate_report.py output/judge-report.json

也可使用项目根目录的一层启动入口:

sudo ./edge-diag start --duration 10 --format markdown

三、命令行使用

edge-diag doctor
edge-diag start [--duration SEC] [--format json|yaml|markdown]
                [--output FILE] [--config FILE]
edge-diag demo  [--format json|yaml|markdown] [--output FILE]
  • doctor:检查内核版本、BTF、权限和 eBPF 运行条件;
  • start:加载真实 eBPF 探针并采集指定时间窗口;
  • demo:无需 BPF 权限,生成五类合成诊断结果;
  • 默认规则文件:config/rules.yaml。

无 root 环境下可以验证报告链路:

./build/edge-diag demo --format json
./build/edge-diag demo --format yaml
./build/edge-diag demo --format markdown

四、一键复现场景

以下脚本会启动负载、运行采集器并自动校验关联对象和诊断结论:

sudo DURATION=5  ./tests/live_cpu_smoke.sh
sudo DURATION=5  ./tests/live_io_smoke.sh
sudo DURATION=12 ./tests/live_memory_oom_smoke.sh
sudo DURATION=5  ./tests/live_lock_smoke.sh
sudo DURATION=30 ./tests/live_syscall_long_smoke.sh
sudo DURATION=10 ./tests/live_idle_smoke.sh

也可以运行整套基础演示:

sudo ./scripts/run_all.sh

内存 OOM 测试会建立临时 cgroup v2 子树并限制其内存,只让特意创建的子进程 触发 OOM。压力脚本应在比赛虚拟机或其他可丢弃测试环境中执行。

五、采集和诊断设计

CPU

  • 通过 sched_switch 配对计算线程运行时间;
  • 通过 sched_wakeup → sched_switch 计算调度等待时间;
  • 统计每线程和系统上下文切换速率;
  • 在内核态维护调度延迟 log2 直方图;
  • 以每核默认 19 Hz 的受限频率采样用户栈;
  • 关联 PID、TGID、命名空间 PID、热点栈和运行队列证据。

工具将 busy loop 表述为“候选根因”,不会仅凭高 CPU 和热点栈声称已经证明 业务逻辑错误。

系统调用

  • 采集 raw_syscalls/sys_enter 和 sys_exit;
  • 按线程和系统调用号统计频率、P99、最大时延及错误;
  • 默认使用 1/8 采样,并在报告中明确原始样本和估算值;
  • 区分原始错误、预期非阻塞错误和可行动错误;
  • 长时延诊断还要求阻塞时间占窗口达到阈值,避免单次慢调用误报。

块设备 I/O

  • 使用带 BTF 类型的块层 issue、requeue、complete 探针;
  • 统计设备 IOPS、吞吐、平均/P99/最大时延和队列深度;
  • 支持慢设备、队列拥堵和块层错误分类;
  • 通过 BPF PID、操作类型和采样 FD 与 /proc/<pid>/fd 做保守路径关联;
  • 输出关联方法和置信度,不把 buffered write、mmap 或 io_uring 中的推测路径 冒充精确因果关系。

内存

  • 采集 page fault、写缺页、直接回收时间和回收页数;
  • 关联 MemAvailable、vmstat、memory PSI、kswapd 和 OOM victim;
  • 只有任务活动与系统内存压力相互支撑时才给出内存异常结论;
  • OOM 用例会校验内核 victim PID 与诊断 PID 完全一致。

锁竞争

  • 配对 futex wait 进入和返回事件;
  • 按 (TGID, futex 地址) 聚合锁实例;
  • 输出等待速率、平均/P99/最大/累计等待、超时率和调度延迟;
  • 保存最长等待者和最近唤醒者的用户栈;
  • 低频定时等待不会仅因超时率高而被判定为锁竞争。

最近唤醒者只是证据,不自动等同于 mutex 所有者。

六、低开销数据路径

高频内核事件不会逐条复制到用户态:

  • 调度、系统调用、I/O、内存和锁事件使用有界 BPF map 聚合;
  • 直方图采用 O(1) 的 log2 分桶;
  • 系统调用和 I/O 明细默认按 1/8 采样;
  • CPU 用户栈默认限制为每核 19 Hz;
  • map 容量固定,能力不足时明确输出降级原因。

七、结构化输出

每条诊断至少包含赛题要求的字段:

  • 异常类型;
  • 关联进程、线程、设备、锁或系统调用;
  • 关键指标和异常时间窗口;
  • 疑似根因及机器可解析的根因代码;
  • 支撑与不支撑结论的证据链;
  • 建议性分析、置信度和能力限制。

JSON 保存完整观测、栈和证据图;YAML 和 Markdown 适合配置集成与评委阅读。 直方图 P99 会被实际最大值约束,保证 P99 <= max。

八、准确率与性能复现

规则冻结后,在原生 openKylin 上运行 30 窗口矩阵:

sudo CONFIRM_FROZEN_RULES=1 REPETITIONS=5 \
  ./scripts/run_accuracy_corpus.sh

测试器会保留误报和漏报对应的有效报告,最后统一计算混淆矩阵,不会因某个 断言失败而提前终止并隐藏失败样本。

性能测试:

sudo REPEATS=3 DURATION=30 make benchmark-io
sudo REPEATS=3 DURATION=30 make benchmark-idle

评委可直接查看:

九、证据校验

完整证据包:

evidence/edge-diag-final-evidence-20260719.tar.gz

外层 SHA-256:

2171ce11f99ff550411bfa5784c0a7d58a6c891267a22ba934d05678ad3735c9

校验和解压:

sha256sum -c evidence/edge-diag-final-evidence-20260719.tar.gz.sha256
mkdir -p output/submission-evidence
tar -xzf evidence/edge-diag-final-evidence-20260719.tar.gz \
  -C output/submission-evidence

./scripts/verify_native_evidence.sh \
  output/submission-evidence/evidence/native-openkylin-x86_64-normal-20260719-v4 \
  x86_64

冻结二进制 SHA-256:

5275afdc5366ba32d8698d4c4a020861ae5c29a52f85e25d454c02aefd76e648

冻结规则 SHA-256:

78b4c574bb1b531b2e316107528c53b8861b69ae56abaae975339691598040a8

十、多架构适配

Makefile 已映射 x86_64、aarch64 和 riscv64 对应的 BPF 目标宏, 并基于目标内核 /sys/kernel/btf/vmlinux 生成 CO-RE skeleton。

  • openKylin x86_64 原生内核:已经完整验证;
  • openKylin ARM64:BPF/ELF 交叉构建和 QEMU 用户态回归通过;
  • ARM64 原生内核加载:尚未验证;
  • RISC-V 运行验证:尚未完成。

十一、目录结构

edge-diag/
├── bpf/          # CO-RE eBPF 探针
├── include/      # 内核态/用户态共享结构
├── src/          # 采集、诊断、配置、输出和 CLI
├── config/       # YAML 规则
├── scripts/      # 安装、复现、平台和证据脚本
├── tests/        # 回归测试、压力场景和断言
├── docs/         # 设计、测试、评分和限制说明
├── evidence/     # 原生报告、指标和完整证据包
├── Makefile
└── README.md

十二、许可证

项目采用 MIT License。BPF 对象同时声明 MIT/GPL 双许可证,以满足部分 内核 helper 的许可证要求。

关于
14.2 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号