目录

Adaptive eBPF Diagnosis

面向 openKylin 与现代 Linux 的自适应性能异常观测和根因诊断工具。系统平时只运行低开销的 baseline eBPF 探针;检测到 CPU、I/O、内存、锁竞争或系统调用异常后,按场景和目标对象租约加载详细探针,采集完成后自动卸载,并生成经过 JSON Schema 校验的 JSON 与 Markdown 诊断报告。

Structure

项目状态

  • 默认闭环覆盖 CPU、块 I/O、内存、futex 锁竞争和系统调用热点五类异常。
  • 支持 x86_64、ARM64 等 libbpf CO-RE 架构构建;完整运行能力取决于目标内核 BTF、tracepoint 和安全策略。
  • 2026-07-23 已在 openKylin 2.0 SP2、Linux 6.6.0-22-generic、x86_64 上完成五类各 3 次正式准确度验收:15/15 正例通过,正常负载对照无报告。
  • 2026-07-24 已完成 5 个随机配对 block、65/65 次性能开销开发实验。结果支持“弹性加载降低 BPF 执行时间、时间加权 map 内存和业务吞吐损失”,但短租约集中加载多个探针会产生明显的 Agent CPU 峰值。

详细结果见 准确度验收结论性能开销实验结论

演示视频见:bilibili

比赛评分点对照

本节按比赛评分细则列出可核查的实现、证据和复现入口。最终分值由评委依据现场结果判定;下文严格区分正式验收、开发实验、构建验证和运行时冒烟,不以功能声明代替实测证据。

功能完成度(40 分)

评分点 项目对应能力 复核方式与当前证据
场景覆盖数量(15 分) 默认闭环覆盖 CPU 饱和/调度压力、块 I/O 延迟、内存压力、futex 锁竞争、系统调用热点 5 类标准异常;从基线触发、目标选择、按需加载到报告收尾均自动完成。 sudo make accuracy-acceptance 一键运行五类各 3 次正例及正常负例;openKylin x86_64 已有 15/15 正例通过的验收结论。各类探针、对象和根因见诊断能力
结构化输出完整性(15 分) schema_version: 1.2 强制包含异常类型、时间窗口、关联对象、关键指标、按探针证据、疑似根因、证据链、建议、采集质量和追溯信息;JSON 为事实来源,中文 Markdown 由同一 JSON 确定性生成。 使用 aebpf validate-report <report.json> 校验机器可解析性,使用 aebpf render-report <report.json> 复现 Markdown;字段定义见 diagnostic-report.schema.json,实际输出见报告样例
多平台适配情况(10 分) 采用 libbpf CO-RE,构建链支持 x86_64/ARM64;doctor 检查 BTF、架构、hook、权限和对象,兼容性报告分为 Build、Load、Scenario 三级。 openKylin 2.0 SP2 / Linux 6.6 / x86_64 已完成正式五场景验收;WSL2 Linux 6.18 / x86_64 已完成真实探针加载和四类场景采集;CI 对 x86_64、ARM64 执行构建/测试。ARM64 目前是 CI 构建证据,不表述为五场景运行验收。

诊断准确性(30 分)

评分点 项目对应能力 复核方式与当前证据
异常识别正确率(10 分) 正式门禁按预先声明的场景真值计算 TP、FP、FN、precision、recall、误报率、漏报率和混淆矩阵,并将 suspected 与证据不足单独统计。 2026-07-23 受控数据集结果为 TP/FP/FN = 15/0/0、precision/recall = 1.0000/1.0000,90 秒正常负载对照报告数为 0。该结果不外推到混合异常、未知负载或未验收平台。
根因定位正确率(12 分) 根因不仅匹配异常类别,还校验 PID、TID、cgroup、函数/调用栈、块设备、futex 地址或 syscall 等适用对象。 正式验收中 CPU、I/O、内存、锁和 syscall 均为 3/3 对象匹配:分别定位 busy_loop、实际块设备、内存压力进程/cgroup、locks 范围内 futex 地址,以及真实 getpid/gettid 调用。
证据链一致性(8 分) 报告将触发指标、flight recorder、命令 ACK、探针完整事件、对象身份、调用栈、根因和建议通过 event/evidence ID 关联;丢失、拒绝、探针失败或证据冲突会使结论降级,不能输出为 confirmed 运行 aebpf validate-report 检查字段和引用完整性;运行 aebpf validate-acceptance 检查真值、对象、采集完整性、哈希和意外确认。报告状态语义见诊断报告

性能开销(15 分)

性能实验同时给出空载 no_agent、平时常驻 baseline_only、详细探针全程常驻和按租约弹性加载四种对照。下表是 2026-07-24 在 openKylin x86_64 上 5 个随机配对 block、65/65 次有效运行的开发实验结果;方括号为 95% 置信区间,业务变化均相对同一 block 的 no_agent

评分点 平时仅 baseline 异常期 elastic leased 评审说明
CPU 开销(4 分) Agent CPU 1.24% [1.20, 1.27] Agent CPU 7.26% [7.12, 7.40] 弹性模式短时间集中 attach/detach 九个探针,控制面 CPU 偏高,是当前明确优化项。
内存开销(3 分) PSS 2.95 MiB;时间加权 map 17.01 MiB PSS 22.45 MiB;时间加权 map 23.35 MiB 弹性模式 map 峰值仍为 75.78 MiB,不能用时间加权值代替峰值。
时延影响(4 分) 平均 +0.87% [-3.01, 4.75];P99 -10.07% [-63.77, 43.63] 平均 +2.93% [-6.76, 12.62];P99 +13.09% [-19.35, 45.53] P99 波动较大且区间跨零,当前数据不支持“P99 显著改善”的结论。
吞吐影响(4 分) -0.78% [-4.48, 2.92] -2.42% [-11.02, 6.18] 相对详细探针全程常驻,弹性模式吞吐提高 10.40% [0.51, 20.29]。

完整原始指标、BPF 执行时间、map、事件丢失和生命周期统计的解释见性能实验结论。该记录来自 dirty tree、单台 x86_64 主机、单一 fio 负载和 20 秒窗口,属于比赛演示/开发证据,不标记为 publication-ready;评委可用 sudo make overhead-smoke 检查管道,再按性能实验设计复现实验。

工程质量与开源规范(15 分)

评分点 项目对应材料 快速复核
代码规范(4 分) C++17 Agent、CO-RE 探针和 Python 后端按职责拆分;协议、配置、事件和报告均使用严格 Schema;关键边界具有 C++/Python 自动化测试。 查看项目结构,运行 make build test
文档完整性(4 分) README 提供使用和架构总览;另有安装部署参数配置功能与设计手动测试故障排查,限制集中列在已知边界 从安装文档完成初始化,再执行 aebpf doctor 和快速开始流程。
复现脚本(4 分) 提供依赖引导、静态/运行时冒烟、五场景准确度验收、性能实验及 openKylin VM 验证脚本。 依次执行 ./scripts/bootstrap.sh --install-systemmake smokesudo make smoke-runtimesudo make accuracy-acceptance;高压负载只在专用测试机运行。
测试说明(3 分) 测试分为代码级、真实内核加载级和场景级;准确度包保存有效配置、独立真值、负载输出、诊断日志、原始报告、对象哈希和 SHA256SUMS 输入、步骤和预期根因见手动测试指南,JSON/Markdown 输出见报告样例,完整命令见测试

工作原理

Linux 内核
  sched / block / memory / futex / raw_syscalls
       |
       | eBPF maps / Ring Buffer / perf event
       v
C++17 Agent
  常驻 baseline -> 读取 /proc、/sys 和 BPF map -> 周期遥测
  接收 LOAD/UNLOAD -> 目标过滤 -> 事件批处理 -> 租约卸载
       |
       | HTTP/JSON(默认仅 loopback)
       v
Python 诊断后端
  指标派生 -> 滚动异常检测 -> 候选对象选择 -> 探针编排
  事件校验/去重/关联 -> 根因门槛判断 -> JSON + Markdown 报告

默认链路如下:

  1. Agent 启动时加载 baseline;加载失败会直接退出,避免在缺少基础观测时提供不完整服务。
  2. Agent 默认每秒采集一次 CPU、I/O、内存、futex 和系统调用基础指标,并附带 host、boot、内核、架构和 Agent 实例身份。
  3. 后端同时使用绝对阈值和滚动基线检测异常,保留默认 30 秒的触发前 flight recorder。
  4. 后端从基础遥测中选择 PID、TID、cgroup、块设备或 syscall,并向 Agent 发送带有限租约的 LOAD 命令。
  5. eBPF 详细探针在内核侧执行目标过滤;Agent 批量转发事件,后端执行 Schema 校验、会话匹配、身份校验和 event ID 去重。
  6. 租约到期、目标退出或异常恢复后,Agent detach 探针并异步排空事件;后端等待采集结果后生成报告。
  7. 更具体的 I/O、内存、锁或系统调用信号优先于通用 CPU 压力,避免将同一故障重复确认为多个根因。

诊断能力

场景 默认触发信号 按需探针 主要关联对象 可确认根因
CPU 饱和/调度压力 CPU busy、每 CPU 上下文切换 runqlatoncpu PID、TID、cgroup、函数/栈 CPU_COMPUTE_HOTSPOTCPU_SCHEDULER_PRESSURE
块 I/O 延迟 单设备 I/O busy biolatency major/minor、块设备、request BLOCK_IO_LATENCYBLOCK_DEVICE_CONGESTION
内存压力 可用内存低或快速下降、direct reclaim、kswapd mempressureoomkill PID、cgroup、RSS、页分配/回收栈、OOM victim MEMORY_ALLOCATION_PRESSUREMEMORY_RECLAIM_PRESSUREOOM_VICTIM_SELECTED
futex 锁竞争 每 CPU 成功 futex wait rate locksensor PID、TID、cgroup、futex 地址、等待调用点、近期 waker FUTEX_WAIT_CONTENTION
系统调用热点 采样后的总调用率、单 syscall 占比或慢调用率 syscall_hotspot PID、TID、syscall ID、用户/内核栈 HIGH_FREQUENCY_SYSCALL_HOTSPOTHIGH_LATENCY_SYSCALL_HOTSPOT

关键证据约束:

  • oncpu 默认使用 49 Hz perf event 采样。只有样本量、用户栈捕获质量、符号解析覆盖率和 Top-1 热点集中度均达标时,才确认函数级 CPU_COMPUTE_HOTSPOT
  • biolatency 通过 request 指针关联 insert、issue 和 complete,可区分总延迟、队列延迟、队列深度和 I/O 错误;当前只归因到块设备,不归因到文件。
  • mempressure 采集 RSS 分类、页分配汇总、页缓存加入、direct reclaim 和 kswapd 活动;oomkill 记录内核选中的 OOM victim。
  • locksensor 将高同步活动与业务性能退化分开。确认 FUTEX_WAIT_CONTENTION 还需要总等待、平均/P99、热点锁集中度以及外部提供的业务吞吐下降证据;缺少吞吐证据时保持 suspected
  • syscall_hotspot 的每个租约必须同时指定 target_pidtarget_syscall_idpollepoll_waitfutex、timer wait、child wait 等预期阻塞调用不会仅凭 enter-to-exit wall-clock 时间被确认为高延迟根因。
  • CPU、系统调用、内存、锁和缺页事件共用统一栈符号化器,保留原始地址、模块、ELF/内核 Build ID、偏移、符号名和 resolved 状态;符号不可用时显式输出 [unknown],不会猜测函数名。

探针清单

探针 角色 主要 hook 默认自动闭环
baseline 常驻 CPU 运行时间、futex 与 syscall 采样基线 raw_syscalls、futex syscall、sched_switch 必选常驻
runqlat 线程 wakeup 到上 CPU 的运行队列延迟 sched_wakeupsched_wakeup_newsched_switch CPU
oncpu PID/cgroup 范围内的用户/内核栈采样 perf_event CPU
biolatency 块请求总延迟、排队延迟与队列深度 block_rq_insert/issue/complete I/O
mempressure RSS、页分配、页缓存和回收活动 sched_switchmm_page_alloc、filemap、vmscan 内存
oomkill OOM victim 证据 oom/mark_victim 内存
locksensor futex 等待、热点地址、调用点和近期唤醒者 futex enter/exit
syscall_hotspot 目标 syscall 次数、耗时、直方图和栈 raw_syscalls:sys_enter/sys_exit 系统调用
pagefault 目标用户态缺页采样 page_fault_user 否,实验性
tcpconnlat 成功 connect() 调用延迟 sys_enter_connect/sys_exit_connect 否,实验性

pagefaulttcpconnlat 可以由 Agent 加载,也用于性能实验,但目前没有进入默认异常检测和根因报告闭环。

项目结构

ai_adaptive_ebpf/
|-- aebpf                         # 统一 CLI 入口
|-- Makefile                      # 构建、测试、运行和实验入口
|-- config/default.yaml           # 唯一默认运行配置
|-- agent/
|   |-- src/                      # C++17 Agent、协议、生命周期、符号化
|   |-- rules.json                # 后端失联时的本地 CPU/I/O 规则
|   |-- probes/                   # 生成的 *.bpf.o(不进入 Git)
|   `-- third_party/              # cpp-httplib、nlohmann/json 子模块
|-- bpf_probes/                   # libbpf CO-RE 内核程序
|-- backend/aebpf/                # Flask 后端、检测器、编排和报告引擎
|-- schemas/                      # 配置、命令、事件、报告和准确度证据 Schema
|-- tests/                        # Python unittest 与 C++ 测试程序
|-- scripts/                      # 引导、负载、冒烟、准确度、性能和 VM 脚本
|-- packaging/                    # systemd unit 和生产路径配置
|-- docs/                         # 安装、配置、测试、限制和设计文档
|-- conclusion/                   # 已提交的实验结论
|-- paper/                        # 论文 LaTeX 与参考文献
`-- validation-results/           # 本机实验产物(不进入 Git)

后端主要模块:

  • detectors.py:确定性滚动异常检测器。
  • engine.py:指标派生、冲突处理、对象选择、探针编排和会话恢复。
  • reports.py:事件关联、根因门槛、采集完整性和结构化报告。
  • report_markdown.py:从已校验 JSON 确定性渲染中文 Markdown。
  • protocol.py:Agent 命令客户端、重试和 ACK 校验。
  • doctor.pycompatibility.py:环境检查和兼容性证据。
  • server.pycli.py:HTTP 服务和统一命令行。

Agent 主要模块:

  • agent.cpp/.hpp:线程管理、baseline 遥测、命令服务、离线规则和事件发送。
  • bpf_manager.cpp/.hpp:BPF object 加载、map 参数注入、attach、poll、detach 和 drain。
  • command_protocol.cpp/.hpp:命令认证、字段、白名单和幂等约束。
  • diagnostic_batch.cpp/.hpp:事件批次数量和字节限制。
  • timer_manager.cpp/.hpp:有限租约和 watchdog 卸载。
  • stack_symbolizer.cpp/.hpp:用户/内核地址、ELF、DWARF、Build ID 和 kallsyms 符号化。

环境要求

推荐目标为 openKylin 2.0 SP2 或同类现代 Linux,内核 6.6+。最低工程要求:

  • 内核提供可读的 /sys/kernel/btf/vmlinux
  • Clang/LLVM、GCC/G++、Make、pkg-config;
  • libbpf、libelf、bpftool;
  • Python 3.10+、venv 和 pip;
  • Git 与初始化完成的子模块;
  • 运行内核探针时使用 root,或目标内核接受的 CAP_BPFCAP_PERFMON,部分环境还需要 CAP_SYS_ADMIN
  • 准确度和性能实验额外需要 stress-ngfiofindmntshufsha256sum 等工具。

Kernel lockdown、LSM、容器能力限制、受限 /proc/kallsyms 或缺失 tracepoint 都可能影响探针加载或符号解析。先运行 aebpf doctor,不要仅以编译成功代替目标内核 attach 验证。

快速开始

1. 初始化

git clone --recurse-submodules <repository-url>
cd ai_adaptive_ebpf
./scripts/bootstrap.sh --install-system

bootstrap.sh 会安装或检查系统依赖,创建 .venv,安装 backend/requirements.txt 中固定版本的 Python 依赖,生成当前内核专用的 bpf_probes/vmlinux.h,并创建权限为 0600.runtime/command-token

已有系统依赖时使用:

git submodule update --init --recursive
./scripts/bootstrap.sh

只安装构建依赖而不安装 fiostress-ng 时使用 ./scripts/bootstrap.sh --install-build-system

2. 构建与静态验证

make build
make test
make smoke

构建结果:

  • bpf_probes/*.bpf.c -> agent/probes/*.bpf.o
  • agent/src/*.cpp -> agent/agent

3. 运行内核 attach 冒烟

mkdir -p validation-results
sudo make smoke-runtime

该测试启动临时后端和 Agent,确认 baseline 遥测到达,并逐一 LOAD/UNLOAD 默认启用的详细探针,检查丢失和拒绝计数。它验证“能加载”,不验证五类负载的诊断准确度。

4. 启动诊断

一条命令运行后端与 Agent,并在结束时完成活动会话、导出报告数组:

sudo .venv/bin/python ./aebpf diagnose \
  --config config/default.yaml \
  --duration 180 \
  --output reports/session.json

--duration 0 表示持续运行直到收到中断。单个报告会写入 reports/<report-id>.json 和同名 .md--output 是本次进程所有报告的 JSON 数组。

也可以分开运行:

# 终端 1
.venv/bin/python ./aebpf backend --config config/default.yaml

# 终端 2
sudo .venv/bin/python ./aebpf agent --config config/default.yaml

从仓库根目录启动 Agent,确保相对路径形式的配置、规则和探针目录正确解析。

5. 查看状态和报告

# 后端健康、活动诊断数量和遥测身份
curl -s http://127.0.0.1:5000/health | .venv/bin/python -m json.tool

# Agent 中的探针会话、目标、剩余租约和 drain 状态
.venv/bin/python ./aebpf status --config config/default.yaml

# 完成当前活动会话
curl -s -X POST http://127.0.0.1:5000/reports/finalize \
  | .venv/bin/python -m json.tool

# 校验和重新渲染报告
.venv/bin/python ./aebpf validate-report reports/<report-id>.json
.venv/bin/python ./aebpf render-report reports/<report-id>.json

CLI 与 Make 命令

CLI

命令 用途
aebpf backend 启动统一 Flask 诊断后端
aebpf agent 校验配置和令牌后执行 C++ Agent
aebpf diagnose 一体化启动、限时运行、收尾并导出报告
aebpf doctor 检查系统、内核、BTF、hook、对象、权限和令牌
aebpf status 查询 Agent 当前会话;--json 输出机器可读结果
aebpf validate-config 使用 schemas/config.schema.json 校验 YAML
aebpf validate-report 校验单个报告或 diagnose 导出的报告数组
aebpf render-report 从有效 JSON 确定性生成 Markdown
aebpf validate-acceptance 校验完整准确度验收证据包

查看参数:

.venv/bin/python ./aebpf --help
.venv/bin/python ./aebpf <subcommand> --help
.venv/bin/python ./aebpf --version

Make targets

命令 用途 是否需要 root
make bootstrap 执行无系统安装的初始化
make vmlinux 从当前内核 BTF 生成 vmlinux.h 通常否
make probes 编译所有 CO-RE 探针
make agent 编译 C++ Agent
make build 编译探针和 Agent
make test 运行全部 C++ 与 Python 测试
make smoke build + test + doctor + Schema/脚本检查 视 doctor 环境而定
sudo make smoke-runtime 真实内核 LOAD/UNLOAD 冒烟
sudo make accuracy-scenarios 五类三次正例和正常负例
sudo make accuracy-development 单次短窗口准确度开发检查
sudo make accuracy-acceptance 固定发布门槛正式准确度验收
sudo make overhead-smoke 2 次短性能实验管道检查
sudo make overhead-experiment 正式随机配对性能实验
make overhead-analyze OVERHEAD_RAW=... 从现有 raw.json 重建统计
sudo make oncpu-validation 函数级 CPU 热点专项验收
make fresh-clone-test 在排除生成物的临时副本中初始化、构建和测试
make run-backend 启动后端
sudo make run-agent 构建 C++ Agent 后启动(探针对象需已构建)
make clean 删除 Agent、探针、测试二进制和 vmlinux.h

另有 openkylin-vm-imageopenkylin-vm-validationopenkylin-iso-full 用于 openKylin ISO/VM 验证。目标机验证步骤见 openKylin 验证说明

配置

config/default.yaml 是规范默认配置。每次 CLI 调用都会使用 schemas/config.schema.json 校验,未知键、错误类型、越界值和启用但无探针的诊断项会被拒绝。

默认服务与会话参数:

配置 默认值
后端监听 127.0.0.1:5000
Agent 命令监听 127.0.0.1:9091
baseline 周期 1 秒
滚动窗口 12 个样本
动态敏感度 3.0 标准差
flight recorder 30 秒
CPU / I/O / 锁 / syscall 租约 60 秒
内存最长租约 300 秒,可因目标退出或恢复提前结束

默认绝对触发阈值:

指标 阈值
cpu_busy_ratio 0.90
io_busy_ratio 0.70
memory_available_ratio 0.10
memory_available_drop_rate_per_second 0.20
context_switch_rate_per_cpu 5000/s
futex_wait_rate_per_cpu 20/s
direct_reclaim_rate_per_second 1000 pages/s
kswapd_scan_rate_per_second 1000 pages/s
syscall_rate_per_second 10000/s
slow_syscall_rate_per_second 0.1/s

阈值只负责打开诊断会话,不等价于根因确认。每类报告还有独立的事件质量、对象匹配和完整性门槛。系统调用与锁竞争的细分策略见 配置参考

后端失联时,Agent 会执行 agent/rules.json 中的离线规则:CPU busy 超过 0.90 时加载 runqlat 60 秒,设备 I/O busy 超过 0.70 时加载 biolatency 60 秒。离线事件只保存在最多 10000 条的内存队列中,重启不持久化。

HTTP 接口与安全边界

后端接口

方法 路径 作用
GET /health 服务状态、活动会话、遥测序号和实例身份
POST /telemetry 接收基础遥测对象
POST /diag_data 接收单条或最多 1000 条诊断事件
GET /reports 列出当前后端进程生成的报告
POST /reports/finalize 卸载活动探针并完成全部报告

后端请求体上限为 1 MiB。Agent 每批最多发送 1000 条或 768 KiB,内存事件队列最多 10000 条;丢失、拒绝和重复事件会分别计数。

Agent 命令接口

Agent 提供认证的 POST /commandGET /status。命令协议支持 LOAD / UNLOAD,并实现:

  • 最少 32 字符、权限不宽于 0600 的共享令牌和常量时间比较;
  • 16 KiB 请求限制、严格字段校验和探针白名单;
  • command_id 幂等缓存和冲突检测;
  • 会话所有权、同探针互斥和 PROBE_BUSY
  • 绝对单调时钟截止时间、有限租约和 watchdog;
  • detach 后立即 ACK、后台异步 drain 和完整丢失计数。

默认配置只监听 loopback,但传输仍是普通 HTTP。跨主机部署必须增加 TLS 或受认证代理,不要直接暴露 5000/9091。命令令牌、.runtime/、报告、日志、虚拟环境和主机生成的 BPF 对象不得提交到 Git。

诊断报告

JSON 是唯一事实来源,必须通过 schemas/diagnostic-report.schema.json(当前 schema_version: 1.2)。同名中文 Markdown 只从已校验 JSON 确定性生成,不调用大模型,也不读取额外运行时状态;状态、异常类型和根因使用中文解释,并保留原始代码便于程序对照。

报告包含:

  • report/session ID、异常类型和时间窗口;
  • 进程、线程、cgroup、设备、锁或 syscall 等关联实体;
  • baseline 与详细探针聚合指标;
  • 按探针分组的字段覆盖、身份、资源和有界代表性完整事件;
  • 根因代码、摘要和置信度;
  • 触发事实、flight recorder、命令 ACK、诊断事件和栈;
  • event/evidence ID 可追溯链;
  • 请求/加载探针、接收/丢失/拒绝数量和终止原因;
  • host、boot、内核、架构、工具和检测器版本;
  • 包含 actionrationaleriskverifyrollback 的结构化处置建议。

报告状态必须按证据解释:

状态 含义
confirmed 场景证据、对象关联和采集完整性达到确认门槛
suspected 有候选证据,但证据质量不足、发生冲突或采集不完整
insufficient_evidence baseline 检测到异常,但详细事件不足以确认根因
failed 请求的诊断探针均未成功加载

suspectedinsufficient_evidencefailed 都不能表述为已确认根因。Ring Buffer/Agent 队列丢失、后端拒绝、部分探针失败、卸载失败或更具体信号冲突会使结论降级。

测试

测试分为代码级、内核加载级和真实场景级,三者不能互相替代。

自动化测试

make test

当前套件包含 3 个 C++ 测试程序和 202 个 Python unittest 测试方法:

  • C++:命令协议、诊断批次限制、栈符号化;
  • Python:CLI、配置 Schema、滚动检测器、doctor、协议重试/ACK、后端 API;
  • 诊断引擎:五类异常触发、对象关联、根因门槛、会话恢复、冲突降级、事件去重与采集完整性;
  • 验收工具:真值、混淆矩阵、重复次数、hash/路径防篡改和正常负例;
  • 性能工具:随机计划、配对统计、Student-t 置信区间、map/事件/生命周期统计;
  • 场景脚本:五类覆盖、系统调用语义保护、内存隔离和运行时收尾。

2026-07-29 本次 README 更新时的 WSL 验证结果为:3 个 C++ 测试程序通过,202 个 Python 测试通过,Ran 202 tests ... OK;测试入口同时验证了配置、报告 Schema、确定性 Markdown 渲染和四组场景样例。

静态 smoke

make smoke

该目标执行 build、全部测试、doctor、默认配置校验、示例报告校验和关键脚本存在性检查。

运行时 smoke

sudo AEBPF_RUNTIME_EVIDENCE="$PWD/validation-results/runtime-smoke.json" \
  make smoke-runtime

它验证真实内核上的 baseline、默认详细探针加载/卸载、目标参数、遥测传输和零丢失,不产生准确度结论。

Fresh clone 测试

make fresh-clone-test

脚本把源码复制到临时目录,排除 .venv.runtime、构建物、报告和实验产物,然后重新 bootstrap、build、test 和校验示例报告,用于发现对本机生成文件的隐式依赖。

手动负载验证

先启动后端和 Agent,一次只运行一种负载,场景之间等待会话结束和主机恢复。常用入口:

# CPU
stress-ng --cpu "$(nproc)" --cpu-method matrixprod --timeout 60s --metrics-brief

# I/O:只在非生产、磁盘支持的测试路径运行
./scripts/generate_io_load.sh

# 锁
gcc -O2 -g -pthread scripts/contention.c -o /tmp/aebpf-contention
/tmp/aebpf-contention convoy 60 8

# 系统调用频率/延迟/等待负例
gcc -O2 -g -pthread scripts/syscall_hotspot_workload.c -o /tmp/aebpf-syscall
/tmp/aebpf-syscall --duration 60 --mode frequency
/tmp/aebpf-syscall --duration 60 --mode latency
/tmp/aebpf-syscall --duration 60 --mode wait

内存和高强度 I/O 测试可能触发 reclaim、swap、OOM 或显著业务抖动,只应在一次性虚拟机或专用测试机运行。完整步骤、预期根因和报告判定见 手动测试指南

准确度测试

开发检查

sudo make accuracy-development

该目标每类只运行 1 次、单次 30 秒、不执行正常负例,可隔离 detector,用于快速调试。它会标记为 development evidence,不能通过正式准确度验收器,也不能替代发布验收。

正式验收

sudo make accuracy-acceptance

.venv/bin/python ./aebpf validate-acceptance \
  validation-results/accuracy-acceptance.json

(cd validation-results && \
  sha256sum -c accuracy-acceptance-artifacts/SHA256SUMS)

正式门禁使用固定发布配置,所有 detector 同时启用;CPU、I/O、内存、锁和系统调用五类正例各重复 3 次,使用固定种子随机交错,并运行 90 秒正常事件循环负例。默认每次正例负载 120 秒、预热 35 秒、冷却 15 秒。

每个正例只有在以下条件全部满足时通过:

  • 状态为 confirmed,异常类型与根因码匹配预先声明的真值;
  • PID/TID/cgroup、块设备、futex 地址/符号或 syscall 等适用对象与独立负载真值匹配;
  • 负载注入本身有效;
  • collection 完整,无探针失败、事件丢失或后端拒绝;
  • 同一窗口没有其他异常类型的意外 confirmed 报告。

正常对照必须执行真实低频 poll/openat/newfstatat 工作负载且报告数组为空。suspected 和主动放弃确认不直接计为 false positive,但必须单独统计;意外 confirmed 才计入错误结论。

证据包包括:

  • precision、recall、误报率、漏报率、对象定位正确率和混淆矩阵;
  • 每轮有效配置、工作负载 stdout/stderr、独立真值、诊断日志和原始报告;
  • 源配置和各 probe object 的 SHA-256;
  • SHA256SUMS 完整性清单和人类可读 Markdown 摘要。

已接受的 x86_64 结果

2026-07-23 的 openKylin x86_64 记录:

指标 结果
正向运行 15
True positives / false positives / false negatives 15 / 0 / 0
Precision / recall 1.0000 / 1.0000
误报率 / 漏报率 0.0000 / 0.0000
对象定位正确率 1.0000
目标 suspected / insufficient_evidence 0 / 0
辅助 suspected 报告 3
90 秒正常负载对照报告 0

该结论只覆盖已声明的五类受控场景和一个正常对照,不外推到混合异常、长期生产流量或未验收架构。主机生成的 validation-results/ 不进入 Git;提交内保留的是结论与证据索引,详见 准确度实验设计准确度证据索引

性能测试

性能实验使用随机化配对 block。每个 repetition 以相同 fio 随机种子运行 13 种模式,顺序重新随机:

  1. no_agent:只有 fio;
  2. baseline_only:Agent + baseline;
  3. 9 个 detailed:<probe>:baseline 分别加一个详细探针;
  4. always_on_detailed:9 个详细探针在整个测量期常驻;
  5. elastic_leased:baseline 常驻,9 个详细探针只在受控租约内加载。

默认前台负载是 4 KiB direct random read、queue depth 32 的单 fio 线程。测试记录:

  • fio 吞吐、IOPS、平均完成延迟和 P99;
  • Agent CPU、RSS 和 PSS;
  • 每个 BPF program 的 run_time_nsrun_cnt 和 ns/run;
  • map 内存、峰值与按实际租约 duty cycle 计算的时间加权值;
  • Ring Buffer 记录/字节、内核 drop、Agent drop 和 oncpu 聚合损失;
  • 每个探针的加载 ACK、detach ACK 和完整 drain 时间;
  • 均值、样本标准差和双侧 95% Student-t 置信区间。

管道冒烟

sudo make overhead-smoke

该目标只执行 2 个 repetition、8 秒测量窗口,用于检查实验管道,结果不能作为发布数据。

正式运行

在专用测试磁盘或明确的非生产测试文件上运行:

make build
sudo ./scripts/overhead_experiment.py run \
  --repetitions 5 \
  --duration 60 \
  --warmup 10 \
  --cooldown 5 \
  --elastic-seconds 6 \
  --workload-file /path/on/dedicated-device/aebpf-overhead.fio \
  --file-size 1G

可用 --cpus 2-5 固定 fio CPU 集,减少调度噪声。至少 5 个 repetition 且 clean repository 才满足工具的 publication_ready 基线;最终比赛/论文数据在时间允许时建议 10 个 repetition。

默认输出为 validation-results/overhead-<UTC timestamp>/

  • raw.json:不可变输入、随机计划、主机身份、对象哈希和每次运行;
  • runs/.../fio.jsonagent.log:逐次原始材料;
  • summary.json:机器可读统计、完整性和 publication readiness;
  • summary.md:核心模式、单探针、BPF program、map、事件和生命周期表。

中断后只有在同一次 boot 且 Agent、runner 和所有 probe object 哈希仍一致时才可继续:

sudo ./scripts/overhead_experiment.py run \
  --resume validation-results/overhead-<timestamp>/raw.json

不重新运行负载即可重建统计:

./scripts/overhead_experiment.py analyze \
  validation-results/overhead-<timestamp>/raw.json

不要接受 raw.json.status != completesummary.json.complete != truepublication_ready == false 或重复次数不足的结果。map 的 capacity_estimate 不能当作实际常驻内存;未触发事件的 probe 也不能当作最坏开销,需同时查看 BPF run_cnt

2026-07-24 开发实验摘要

历史实验为 5 个 block、65/65 次有效运行,20 秒测量、10 秒 warm-up,弹性租约 2 秒:

模式 Agent CPU PSS 均值 BPF 时间 时间加权 map 吞吐变化(对 no-agent)
baseline-only 1.24% 2.95 MiB 10.94 ms/s 17.01 MiB -0.78%
always-on detailed 1.60% 34.08 MiB 30.15 ms/s 75.78 MiB -11.58%
elastic leased 7.26% 22.45 MiB 13.70 ms/s 23.35 MiB -2.42%

弹性模式相对全程常驻,配对均值减少 16.45 ms/s BPF 执行时间和 52.43 MiB 时间加权 map,吞吐提高 10.40%,但 Agent CPU 增加 5.66 个百分点。该结果的 Git 记录为 1ae57ac...dirty=true,因此属于开发/演示证据,不是 publication-ready 结论。完整置信区间与限制见 性能实验设计实验结论

兼容性与 CI

兼容性证据分三级:

  1. Build:eBPF object、C++ Agent、Python 测试和 Schema 通过;
  2. Load:baseline 和详细探针在目标内核成功加载与卸载;
  3. Scenario:标准负载触发符合真值的有效报告。

GitHub Actions 在 x86_64 和 ARM64 runner 上执行 build/test,并在 openKylin 2.0 容器中验证用户态依赖。容器共享宿主内核,因此不能证明 openKylin 内核 attach;完整 runtime job 需要带 openkylin 标签的 6.6+ self-hosted runner。

目标机完整流程:

./scripts/bootstrap.sh --install-system
make clean build test
mkdir -p validation-results
sudo AEBPF_RUNTIME_EVIDENCE="$PWD/validation-results/runtime-smoke.json" \
  make smoke-runtime
sudo make accuracy-scenarios
AEBPF_RUNTIME_EVIDENCE="$PWD/validation-results/runtime-smoke.json" \
AEBPF_SCENARIO_EVIDENCE="$PWD/validation-results/accuracy-scenarios.json" \
  ./scripts/compatibility-report.sh validation-results/openkylin-runtime.json

runtime 与 scenario 证据必须来自同一 host、boot、kernel 和 architecture。只有 openkylin_accuracy_runtime.status == pass 才能声明目标平台已完成准确度运行验证。详见 openKylin 验证说明

systemd 部署

packaging/ 提供参考 unit 和生产路径配置:

  • 代码与虚拟环境:/opt/aebpf
  • 配置与命令令牌:/etc/aebpf
  • 报告和运行数据:/var/lib/aebpf
  • 后端以 aebpf 用户运行;
  • Agent 以 root 运行,并限制为 CAP_BPF CAP_PERFMON CAP_SYS_ADMIN capability 集。

部署前应审查目标发行版的 systemd sandbox、kernel lockdown、LSM、报告目录权限和 TLS/代理配置。完整命令见 安装与部署

常见问题

缺少 BTF 或 vmlinux.h

test -r /sys/kernel/btf/vmlinux
make vmlinux

若 BTF 不可读,需要切换到启用 BTF 的内核;不要从另一台不同内核的主机复制 vmlinux.h

Agent 启动后没有报告

依次确认:

  1. /health.telemetry_samples 是否持续增长;
  2. 空闲时是否已有其他进程触发会话;
  3. 压力强度和持续时间是否跨过默认触发阈值;
  4. aebpf status 是否出现目标探针与正确 PID/cgroup/device/syscall;
  5. 是否过早调用 /reports/finalize
  6. 报告是否为 suspectedinsufficient_evidence,以及 collection 是否完整。

探针 attach 失败

.venv/bin/python ./aebpf doctor --config config/default.yaml --json
sudo bpftool feature probe

记录发行版、uname -a、BTF、tracepoint、权限和 Agent/libbpf verifier 日志。容器内 root 不一定拥有宿主 BPF 能力。

栈无法解析

测试程序使用 -g -fno-omit-frame-pointer 且不要 strip。检查目标进程是否在采集结束前退出、/proc/<pid>/maps 是否可读,以及 /proc/kallsyms/debuginfo 是否受限。未解析帧是显式降级,不应被解释成某个具体函数。

更多排查项见 故障排查

已知边界

  • 当前没有 block I/O 到具体文件的可靠因果归因。
  • tcpconnlat 尚未完整关联目标 IP、端口和 socket 元数据,也未进入默认网络诊断。
  • pagefault 有采样能力,但没有默认缺页异常类别和独立根因门槛。
  • futex 的近期 waker 只能证明它唤醒过等待者,不能可靠证明它就是锁 owner。
  • 锁性能退化确认依赖业务提供当前/基线吞吐,框架不会用 CPU 或 futex 次数猜测业务吞吐。
  • 离线队列不落盘,Agent 重启会丢失尚未发送的离线事件。
  • 当前没有 Kubernetes 元数据映射、Web 仪表盘、自动修复或大模型自主推理。
  • 单一 x86_64 主机上的受控准确度与 fio 开销结果不能外推到所有内核、架构和生产负载。

开发约定

  • C/C++ 使用 4 空格、声明行左大括号、函数和变量 snake_case、类名 PascalCase,保持 -Wall -Wextra -Wpedantic 无警告。
  • Python 使用 4 空格和 snake_case;新增测试命名为 tests/test_<feature>.py
  • probe 名称必须在文件名、事件 probe_name、Agent 白名单、JSON 命令、配置和后端决策中完全一致。
  • 不修改 agent/third_party/,除非明确升级 vendored dependency。
  • 不提交令牌、虚拟环境、报告、日志、vmlinux.hagent/probes/、Agent 二进制或主机实验产物。
  • 提交前至少运行 make test;涉及 eBPF hook、命令协议或运行路径时再运行 make smokesudo make smoke-runtime 和对应场景。

延伸文档

License

本项目使用 MIT License

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

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