Document fsession PID and shutdown semantics

This commit is contained in:
LinuxDev9002
2026-07-18 14:14:31 -07:00
parent 48a4e3fb70
commit 7e984142d5
2 changed files with 16 additions and 10 deletions

View File

@@ -23,6 +23,8 @@ SERVICE_PID=$(pgrep -n my-service)
sudo ./fsession_latency --pid "$SERVICE_PID" --threshold-us 10000 --duration 30 sudo ./fsession_latency --pid "$SERVICE_PID" --threshold-us 10000 --duration 30
``` ```
`--pid` compares against the TGID returned by `bpf_get_current_pid_tgid()`, which is always the TGID in the host (initial) PID namespace. The `pgrep` example above works for a process running directly on the host. For a process inside a container or nested PID namespace, you must resolve and pass its host-namespace TGID; a namespace-local PID will silently match nothing.
CLI usage: CLI usage:
```text ```text
@@ -143,9 +145,10 @@ The user-space program in `fsession_latency.c` performs these steps:
1. Parse CLI arguments (threshold, duration, PID filter). 1. Parse CLI arguments (threshold, duration, PID filter).
2. Open the BPF skeleton and set `rodata` constants (`threshold_ns`, `target_tgid`) before loading. 2. Open the BPF skeleton and set `rodata` constants (`threshold_ns`, `target_tgid`) before loading.
3. Load and attach the fsession program to `vfs_read`. 3. Load and attach the fsession program to `vfs_read`.
4. Create a ring buffer and poll it with a 100 ms timeout until the duration expires or a signal arrives. 4. Create a ring buffer and poll it with a 100 ms timeout until the duration expires or a signal arrives. Print each event as it arrives (comm, tgid, pid, requested bytes, result, latency in microseconds).
5. Print each event as it arrives (comm, tgid, pid, requested bytes, result, latency in microseconds). 5. Detach the fsession program so BPF statistics stop changing.
6. Print a summary line with aggregate counters from BSS. 6. Call `ring_buffer__consume()` to drain events already submitted to the ring buffer before detach.
7. Print the summary line with stable aggregate counters from BSS.
The summary line exposes ring-buffer drops so the operator knows if events were lost under load. The summary line exposes ring-buffer drops so the operator knows if events were lost under load.
@@ -183,7 +186,7 @@ The test validates:
1. An unmatched PID (2^32 - 1) produces zero calls, proving the TGID filter works. 1. An unmatched PID (2^32 - 1) produces zero calls, proving the TGID filter works.
2. A 10-second threshold (10,000,000 us) produces no slow events even though reads complete, proving the threshold comparison works. 2. A 10-second threshold (10,000,000 us) produces no slow events even though reads complete, proving the threshold comparison works.
3. A 10 ms threshold with a pipe read delayed by 50 ms produces at least one slow event, proving the end-to-end reporting path works. 3. A 10 ms threshold with a pipe read delayed by 50 ms produces at least one slow event, proving the end-to-end reporting path works.
4. Threshold 0 with continuous target-TGID reads through the one-second deadline produces calls and events, and the CLI still exits successfully. This protects the normal-success exit path when the final `ring_buffer__poll()` call consumes events. 4. Threshold 0 with continuous target-TGID reads through the one-second deadline produces calls and events, and the CLI still exits successfully. The test also asserts `slow == events + dropped`, so every slow call at the window boundary is either delivered or explicitly counted as a ring-buffer reservation drop.
## Requirements ## Requirements
@@ -201,7 +204,7 @@ The test validates:
- Measures time inside `vfs_read` only. This is not full request latency, storage-device service time, or application p99. - Measures time inside `vfs_read` only. This is not full request latency, storage-device service time, or application p99.
- Covers only paths that invoke `vfs_read`. mmap and other paths that bypass it are invisible. - Covers only paths that invoke `vfs_read`. mmap and other paths that bypass it are invisible.
- Exact TGID filter only. No cgroup, process-tree, path, inode, mount, or container selector. - Exact TGID filter only. No cgroup, process-tree, path, inode, mount, PID-namespace, or container selector. The filter operates on the host-namespace TGID; there is no way to pass a namespace-local PID or select by container runtime.
- One-shot duration. Not a daemon, alerting system, or metrics exporter. - One-shot duration. Not a daemon, alerting system, or metrics exporter.
- Ring buffer can drop matching events under load. The `dropped` counter exposes that condition; other counters remain aggregate observations. - Ring buffer can drop matching events under load. The `dropped` counter exposes that condition; other counters remain aggregate observations.
- Command names can repeat and PID reuse is possible outside the bounded tracing window. - Command names can repeat and PID reuse is possible outside the bounded tracing window.

View File

@@ -23,6 +23,8 @@ SERVICE_PID=$(pgrep -n my-service)
sudo ./fsession_latency --pid "$SERVICE_PID" --threshold-us 10000 --duration 30 sudo ./fsession_latency --pid "$SERVICE_PID" --threshold-us 10000 --duration 30
``` ```
`--pid` 比较的是 `bpf_get_current_pid_tgid()` 返回的 TGID,即宿主机(初始)PID 命名空间中的 TGID。上面的 `pgrep` 示例适用于直接运行在宿主机上的进程。如果目标进程位于容器或嵌套 PID 命名空间内,必须解析并传入其宿主机命名空间的 TGID;传入命名空间内部的 PID 会静默匹配不到任何进程。
命令行用法: 命令行用法:
```text ```text
@@ -143,9 +145,10 @@ struct latency_stats {
1. 解析命令行参数(阈值、持续时间、PID 过滤器)。 1. 解析命令行参数(阈值、持续时间、PID 过滤器)。
2. 打开 BPF skeleton,在加载前设置 `rodata` 常量(`threshold_ns`、`target_tgid`)。 2. 打开 BPF skeleton,在加载前设置 `rodata` 常量(`threshold_ns`、`target_tgid`)。
3. 加载并附加 fsession 程序到 `vfs_read`。 3. 加载并附加 fsession 程序到 `vfs_read`。
4. 创建 ring buffer,以 100 ms 超时轮询,直到持续时间到期或收到信号。 4. 创建 ring buffer,以 100 ms 超时轮询,直到持续时间到期或收到信号。每收到一个事件立即打印(comm、tgid、pid、请求字节数、结果、延迟微秒数)。
5. 每收到一个事件立即打印(comm、tgid、pid、请求字节数、结果、延迟微秒数)。 5. 解除 fsession 程序的附加,使 BPF 统计计数器不再变化。
6. 打印汇总行,包含从 BSS 读取的聚合计数器。 6. 调用 `ring_buffer__consume()` 排空解除附加前已提交到 ring buffer 的事件。
7. 打印汇总行,此时聚合计数器已稳定。
汇总行中的 `dropped` 字段暴露 ring buffer 丢失事件的情况,让运维人员知道是否有数据丢失。 汇总行中的 `dropped` 字段暴露 ring buffer 丢失事件的情况,让运维人员知道是否有数据丢失。
@@ -183,7 +186,7 @@ sudo make test
1. 不匹配的 PID (2^32 - 1) 产生零次调用,证明 TGID 过滤器有效。 1. 不匹配的 PID (2^32 - 1) 产生零次调用,证明 TGID 过滤器有效。
2. 10 秒阈值 (10,000,000 us) 即使有读操作完成也不产生慢事件,证明阈值比较逻辑正确。 2. 10 秒阈值 (10,000,000 us) 即使有读操作完成也不产生慢事件,证明阈值比较逻辑正确。
3. 10 ms 阈值加上延迟 50 ms 的管道读产生至少一个慢事件,证明端到端上报路径正常工作。 3. 10 ms 阈值加上延迟 50 ms 的管道读产生至少一个慢事件,证明端到端上报路径正常工作。
4. 阈值为 0 时,持续对目标 TGID 执行读操作直到一秒截止时间结束,产生调用和事件,且 CLI 仍然成功退出。该场景保护最后一次 `ring_buffer__poll()` 消费事件后的正常退出路径。 4. 阈值为 0 时,持续对目标 TGID 执行读操作直到一秒截止时间结束,产生调用和事件,且 CLI 仍然成功退出。该场景还断言 `slow == events + dropped`,确保窗口边界的每一个慢调用要么被投递为事件,要么被明确计入 ring buffer 预留失败。
## 环境要求 ## 环境要求
@@ -201,7 +204,7 @@ sudo make test
- 仅测量 `vfs_read` 内部的时间,不等于完整请求延迟、存储设备服务时间或应用 p99。 - 仅测量 `vfs_read` 内部的时间,不等于完整请求延迟、存储设备服务时间或应用 p99。
- 仅覆盖调用 `vfs_read` 的路径。mmap 和其他绕过 `vfs_read` 的路径不可见。 - 仅覆盖调用 `vfs_read` 的路径。mmap 和其他绕过 `vfs_read` 的路径不可见。
- 仅支持精确 TGID 过滤,不支持 cgroup、进程树、路径、inode、挂载点或容器选择器。 - 仅支持精确 TGID 过滤,不支持 cgroup、进程树、路径、inode、挂载点、PID 命名空间或容器选择器。过滤器在宿主机命名空间 TGID 上工作,无法传入命名空间内部的 PID 或按容器运行时选择。
- 单次运行,不是守护进程、告警系统或指标导出器。 - 单次运行,不是守护进程、告警系统或指标导出器。
- Ring buffer 在高负载下可能丢失匹配事件。`dropped` 计数器暴露该情况,其他计数器为聚合观察值。 - Ring buffer 在高负载下可能丢失匹配事件。`dropped` 计数器暴露该情况,其他计数器为聚合观察值。
- 命令名称可能重复,PID 在有界追踪窗口外可能被复用。 - 命令名称可能重复,PID 在有界追踪窗口外可能被复用。