tracer ftrace笔记(9)—— TRACE_EVENT 初始化
基于Linux-5.10
一、内核启动时遍历 trace_event_call 初始化流程
1. TRACE_EVENT()多次展开定义了各种实现函数以后,最终把本 event 的所有的函数和数据存放在一个类型为 struct trace_event_call 的顶层变量中,并且会把指针存放到 section(“_ftrace_events”) 中。在 trace_events 初始化时会逐个遍历 section("_ftrace_events") 中的指针来添加静态的 events。
TRACE_EVENT(sched_blocked_reason, ...) 宏解析后:
static struct trace_event_call __used __section("_ftrace_events") *__event_sched_blocked_reason = &event_sched_blocked_reason;
链接脚本 include/asm-generic/vmlinux.lds.h
#define FTRACE_EVENTS() . = ALIGN(8); \ __start_ftrace_events = .; \ KEEP(*(_ftrace_events)) \ __stop_ftrace_events = .; \
函数调用路径:
trace_init //trace/trace.c trace_event_init //trace/trace_events.c event_trace_enable //trace/trace_events.c
event_trace_enable() 函数:
static __init int event_trace_enable(void) //trace/trace_events.c { struct trace_event_call **iter, *call; int ret; ... /* * 从 section("_ftrace_events") 逐个拿出使用 TRACE_EVENT() 宏定义的 * trace_event_call 指针,并进行初始化 */ for_each_event(iter, __start_ftrace_events, __stop_ftrace_events) { call = *iter; /* 初始化trace_event_call */ ret = event_init(call); if (!ret) /* 挂到全局 ftrace_events 链表上 */ list_add(&call->list, &ftrace_events); } ... return 0; }
event_init() 函数:
static int event_init(struct trace_event_call *call) { int ret = 0; const char *name; /* TRACE_EVENT()定义的就是第一个参数 name 成员 */ name = trace_event_name(call); if (WARN_ON(!name)) return -EINVAL; /* TRACE_EVENT()定义的就是 trace_event_raw_init() */ if (call->class->raw_init) { /* 初始化后注册trace event,就是放在全局hash表 event_hash[key] 上 */ ret = call->class->raw_init(call); if (ret < 0 && ret != -ENOSYS) pr_warn("Could not initialize trace events/%s\n", name); } return ret; }
参考:
深入理解Linux ftrace 之 trace event: https://mp.weixin.qq.com/s/1A02qv5SIEgTEvsN1DWzqQ
posted on 2022-10-11 16:22 Hello-World3 阅读(518) 评论(0) 编辑 收藏 举报