# ktracepoint
面向内核场景的 Rust tracepoint 库,设计目标类似 Linux tracepoint:
- 用宏定义事件与字段
- 运行时按唯一事件 ID 管理
- 支持开关、过滤表达式、回调
- 支持原始事件缓冲区与可读文本输出
- no_std 可用
## 核心能力
- 事件定义:通过 define_event_trace! 一次性生成事件元数据、调用函数、注册函数
- 事件管理:TracePointMap 按 tracepoint ID 索引
- 事件控制:enable/disable、format/id/filter
- 过滤表达式:基于 tp-lexer 按 schema 编译并匹配
- 输出链路:TracePipeRaw + TraceEntryParser
## 快速接入
### 1. 添加依赖
```toml
[dependencies]
ktracepoint = "*"
static-keys = "0.8"
```
### 2. 链接脚本中保留 .tracepoint 段
该库通过 __start_tracepoint / __stop_tracepoint 扫描所有事件元数据。
请将 my_section.ld 的内容并入你的链接脚本,确保 .tracepoint 段被 KEEP。
### 3. 实现 KernelTraceOps
你需要提供:
- time_now
- cpu_id
- current_pid
- trace_pipe_push_raw_record
- trace_cmdline_push
- write_kernel_text
- tracepoint state registry 钩子:read_tracepoint_state、write_tracepoint_state
其中 write_kernel_text 用于 static key 指令补丁。
state registry 钩子用于让你的 OS 自行选择 callbacks 和 filters 的同步策略。
### Callback 限制
`read_tracepoint_state` 可以在 tracing 快路径执行 callbacks 时持有读侧锁。如果你的实现使用 `RwLock` 这类不可重入锁,callback 中不得:
- 注册或注销 tracepoint callback
- 更新 tracepoint filter
- 调用其它需要 `write_tracepoint_state` 的 API
- 递归触发由同一个 state registry 支撑的 tracepoint
违反这些规则可能导致死锁。如果宿主使用 RCU、snapshot 或其它非阻塞读侧机制实现 `read_tracepoint_state`,可以自行放宽这些限制。
### 4. 定义并调用事件
```rust
use ktracepoint::{define_event_trace, KernelTraceOps};
define_event_trace!(
TEST,
TP_kops(Kops),
TP_system(tracepoint_test),
TP_PROTO(a: u32, b: u32),
TP_STRUCT__entry { a: u32, b: u32 },
TP_fast_assign { a: a, b: b },
TP_ident(__entry),
TP_printk(format_args!("a={}, b={}", __entry.a, __entry.b))
);
// 生成函数: trace_TEST / register_trace_TEST / unregister_trace_TEST
trace_TEST(1, 2);
```
提示:TP_STRUCT__entry 会参与字节布局,请确保字段布局符合预期(建议 C 风格布局思路)。
### 5. 初始化管理器
```rust
use ktracepoint::global_init_events;
static_keys::global_init();
let (tracepoints, ext_tracepoints) = global_init_events::<Kops>()?;
// 将 ext_tracepoints 安装到 Kops::read_tracepoint_state 和
// Kops::write_tracepoint_state 使用的 registry 中。
```
### 6. 启用、过滤、消费输出
```rust
use ktracepoint::{TraceFilterFile, TracePointEnableFile, TracePointFormatFile, TracePointIdFile};
let event_id = 0;
let tracepoint = tracepoints.get(&event_id).unwrap();
TracePointEnableFile::new(tracepoint).write('1');
tracepoint.enable_event();
Kops::write_tracepoint_state(event_id, |event| {
let mut filter = TraceFilterFile::new();
filter.write(event, "a > 8 && b > 5").unwrap();
});
// 读取格式描述
let fmt = TracePointFormatFile::new(tracepoint).read();
let id = TracePointIdFile::new(tracepoint).read();
```
## 运行示例
```bash
cd examples
cargo run --example usage
```
示例代码位于 examples/usage.rs,覆盖了:
- 事件定义与触发
- 事件启用与过滤
- 注册 event/raw 回调
- TracePipeRaw 快照读取与文本解析
## 主要公开类型
- KernelTraceOps
- TracePoint / ExtTracePoint / TracePointMap
- TracePipeRaw / TracePipeSnapshot / TracePipeOps
- TraceCmdLineCache / TraceEntryParser
## 参考项目
- DragonOS: <https://github.com/DragonOS-Community/DragonOS/blob/master/kernel/src/debug/tracing/mod.rs>
- Hermit: <https://github.com/os-module/hermit-kernel/blob/dev/src/tracepoint/mod.rs>