ftrace function demo
一、编译期准备:插入 mcount 调用
条件:
内核 .config 含有:
CONFIG_FUNCTION_TRACER=y
CONFIG_DYNAMIC_FTRACE=y
作用:
- 编译时自动为所有函数前插入 call mcount。
- gcc -pg 参数实现此目的。
示例:
do_dentry_open:
call mcount
...
二、运行时 patch:替换 mcount 为 ftrace_caller
动态 ftrace 会用 ftrace_make_call() 把 call mcount 替换为 call ftrace_caller,从而跳转到 ftrace 注册的钩子。
三、执行流程(调用发生时)
以 call do_dentry_open 为例,函数执行触发流程如下:
do_dentry_open()
|
|---> call ftrace_caller <-- 原为 mcount,已被 patch
|
|---> ftrace_ops_list
|
|---> your callback_func(ip, parent_ip, ops, regs)
函数分发器(Trampoline):
void ftrace_caller(void)
{
save_regs_to_stack();
call all ftrace_ops->func();
restore_regs_from_stack();
jmp original_func_body;
}
四、demo
mount -t debugfs none /sys/kernel/debug
# 设置 tracer 类型
echo function > /sys/kernel/debug/tracing/current_tracer
# 设置要跟踪的函数
echo do_dentry_open > /sys/kernel/debug/tracing/set_ftrace_filter
# 清空 trace buffer
echo > /sys/kernel/debug/tracing/trace
# 启动跟踪
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 运行一个触发 open 的命令
ls / > /dev/null
# 查看结果
cat /sys/kernel/debug/tracing/trace
# 停止跟踪
echo 0 > /sys/kernel/debug/tracing/tracing_on
执行cat /sys/kernel/debug/tracing/trace,将看见类似如下内容:
~ # cat /sys/kernel/debug/tracing/trace
# tracer: function
#
# entries-in-buffer/entries-written: 6/6 #P:2
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / _-=> migrate-disable
# |||| / delay
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
sh-101 [001] ..... 33.388469: do_dentry_open <-path_openat
sh-101 [001] ..... 37.068001: do_dentry_open <-path_openat
ls-106 [000] ..... 37.069901: do_dentry_open <-path_openat
ls-106 [000] ..... 37.072422: do_dentry_open <-path_openat
cat-107 [000] ..... 41.571282: do_dentry_open <-path_openat
cat-107 [000] ..... 41.571735: do_dentry_open <-path_openat
字段说明:
| 字段 | 含义 |
|---|---|
ls-106 | 任务名和PID |
[000] | 运行在哪个CPU核上 |
.... | 中断、抢占等状态标志位(见下) |
37.069901 | 时间戳(秒) |
do_dentry_open | 当前调用的函数名(从符号表解析) |
2195

被折叠的 条评论
为什么被折叠?



