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
/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_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; } """
b = BPF(text=bpf_text) print("Tracing fork events... Ctrl+C to exit") b.trace_print()
|
关键说明:
跟踪点参数:
parent
: 父进程的 task_struct
child
: 子进程的 task_struct
- 可访问字段:
pid
(进程ID)、comm
(命令名)等。
使用场景:
- 内核模块:需编译加载,适合深度监控。
- Ftrace:无需编码,动态启用/禁用。
- BPF/BCC:动态注入脚本,安全高效。
注意事项:
- 内核模块需适配目标内核版本(使用
KDIR
编译)。
- 生产环境中避免在跟踪点处理函数中阻塞(如使用
printk
需谨慎)。
- Ftrace 路径可能因系统差异略有不同(如
/sys/kernel/tracing/
)。
验证事件
运行测试命令后,通过以下方式检查事件:
1 2 3 4 5
| dmesg | tail
cat /sys/kernel/debug/tracing/trace_pipe
|
此示例覆盖了从基础内核模块到高级BPF的多种用法,可根据需求选择合适的方式。