Linux 5.10内核trace_sched_process_fork钩子的用法示例

服务器繁忙,请稍后再试。

Linux 5.10内核trace_sched_process_fork钩子的用法示例

在Linux 5.10内核中,trace_sched_process_fork 是一个跟踪点(tracepoint),用于在进程创建(fork/exec)时触发事件。以下是使用该跟踪点的详细示例:

1. 内核模块示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/tracepoint.h>
#include <trace/events/sched.h> // 包含跟踪点声明

// 探测函数
static void trace_fork_handler(void *ignore, struct task_struct *parent, struct task_struct *child)
{
printk(KERN_INFO "FORK: parent_pid=%d (%s) -> child_pid=%d (%s)\n",
parent->pid, parent->comm,
child->pid, child->comm);
}

static int __init trace_init(void)
{
// 注册跟踪点处理函数
int ret = register_trace_sched_process_fork(trace_fork_handler, NULL);
if (ret) {
pr_err("Failed to register tracepoint handler\n");
return ret;
}
printk(KERN_INFO "Tracepoint handler registered\n");
return 0;
}

static void __exit trace_exit(void)
{
// 注销跟踪点
unregister_trace_sched_process_fork(trace_fork_handler, NULL);
printk(KERN_INFO "Tracepoint handler unregistered\n");
}

module_init(trace_init);
module_exit(trace_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");

2. 编译内核模块的 Makefile

1
2
3
4
5
6
7
8
obj-m += fork_tracer.o
KDIR ?= /lib/modules/$(shell uname -r)/build

all:
make -C $(KDIR) M=$(PWD) modules

clean:
make -C $(KDIR) M=$(PWD) clean

3. 使用 Ftrace 直接捕获事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 启用跟踪点
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_process_fork/enable

# 开始捕获
echo > /sys/kernel/debug/tracing/trace # 清空缓冲区
echo 1 > /sys/kernel/debug/tracing/tracing_on

# 执行测试命令(例如:运行一个shell)
/bin/bash -c "echo test"

# 停止捕获
echo 0 > /sys/kernel/debug/tracing/tracing_on

# 查看结果
cat /sys/kernel/debug/tracing/trace

输出示例

1
bash-1234  [000] ...1  7890.123456: sched_process_fork: comm=bash pid=1234 child_comm=bash child_pid=5678

4. BPF 程序示例(使用 BCC 工具)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from bcc import BPF

# 定义BPF程序
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>

TRACEPOINT_PROBE(sched, sched_process_fork) {
struct task_struct *parent = (struct task_struct *)args->parent;
struct task_struct *child = (struct task_struct *)args->child;
bpf_trace_printk("FORK: parent=%d (%s) -> child=%d (%s)\\n",
parent->pid, parent->comm,
child->pid, child->comm);
return 0;
}
"""

# 加载BPF程序
b = BPF(text=bpf_text)
print("Tracing fork events... Ctrl+C to exit")
b.trace_print() # 实时打印输出

关键说明:

  1. 跟踪点参数

    • parent: 父进程的 task_struct
    • child: 子进程的 task_struct
    • 可访问字段:pid(进程ID)、comm(命令名)等。
  2. 使用场景

    • 内核模块:需编译加载,适合深度监控。
    • Ftrace:无需编码,动态启用/禁用。
    • BPF/BCC:动态注入脚本,安全高效。
  3. 注意事项

    • 内核模块需适配目标内核版本(使用 KDIR 编译)。
    • 生产环境中避免在跟踪点处理函数中阻塞(如使用 printk 需谨慎)。
    • Ftrace 路径可能因系统差异略有不同(如 /sys/kernel/tracing/)。

验证事件

运行测试命令后,通过以下方式检查事件:

1
2
3
4
5
# 查看内核日志(模块/BPF)
dmesg | tail

# 查看Ftrace输出
cat /sys/kernel/debug/tracing/trace_pipe

此示例覆盖了从基础内核模块到高级BPF的多种用法,可根据需求选择合适的方式。