Ftrace
注:本文参考 https://zhuanlan.zhihu.com/p/479833554
1. 什么是Ftrace
ftrace是一个内核代码的调试工具,可以让用户获取内核函数的调用信息并进行一系列调试。功能类似于用户态代码打断点或者Java的AOP切面
2. Ftrace原理
实现原理是Linux实现了一套相关的系统在所有函数的入口收集函数的信息(地址,入参等),通过诸如sysfs等机制将相关信息暴露给用户态。那如何实现收集函数信息呢?自己实现这个功能最简单的方法是在函数入口加一个printk或其他类似方法来记录信息。Linux将相关实现放到了gcc编译器中,gcc编译器在编译时在每个函数的入口地址放置一个probe点,这个probe点会调用一个probe函数(gcc默认调用名为mcount的函数),这样这个 probe函数会对每个执行的内核函数进行跟踪(其实有少数几个内核函数不会被跟踪),并打印log到一个内核中的环形缓存(ring buffer)中,而用户可以通过debugfs来访问这个环形缓存中的内容。
3. Ftrace的主要跟踪机制
-
动态探针
可以动态跟踪内核函数的调用栈,包括function tracr,function graph trace两个tracer。其原理是利用mcount机制,在内核编译时,在每个函数入口保留数个字节,然后在使用ftrace时,将保留的字节替换为需要的指令,比如跳转到需要的执行探测操作的代码。
-
静态探针
是在内核代码中调用ftrace提供的相应接口实现,称之为静态是因为,是在内核代码中写死的,静态编译到内核代码中的,在内核编译后,就不能再动态修改。在开启ftrace相关的内核配置选项后,内核中已经在一些关键的地方设置了静态探测点,需要使用时,即可查看到相应的信息。
4. Ftrace控制机制
利用debugfs的echo和cat来设置和获取相关函数调用信息,以下按linux5.4来做一些展开
4.1. ftrace的四类文件
-
提示类:显示当前系统可用的event,tracer 列表
-
控制类:控制 ftrace 的跟踪参数
-
显示类:显示 trace 信息
-
辅助类:一些不明或者不重要的辅助信息
4.2. ftrace的相关函数总结
- Function tracer Function graph tracer :跟踪函数调用
- Schedule switch tracer :跟踪进程调度情况
- Wakeup tracer :跟踪进程的调度延迟,即高优先级进程从进入 ready 状态到获得 CPU 的延迟时间。该 tracer 只针对实时进程。
- Irqsoff tracer :当中断被禁止时,系统无法相应外部事件,比如键盘和鼠标,时钟也无法产生 tick 中断。这意味着系统响应延迟,irqsoff 这个 tracer 能够跟踪并记录内核中哪些函数禁止了中断,对于其中中断禁止时间最长的,irqsoff 将在 log 文件的第一行标示出来,从而使开发人员可以迅速定位造成响应延迟的罪魁祸首
- Preemptoff tracer: 和前一个 tracer 类似,preemptoff tracer 跟踪并记录禁止内核抢占的函数,并清晰地显示出禁止抢占时间最长的内核函数。
- Preemptirqsoff tracer :同上,跟踪和记录禁止中断或者禁止抢占的内核函数,以及禁止时间最长的函数
- Branch tracer:跟踪内核程序中的 likely/unlikely 分支预测命中率情况。 Branch tracer 能够记录这些分支语句有多少次预测成功。从而为优化程序提供线索。
- Hardware branch tracer :利用处理器的分支跟踪能力,实现硬件级别的指令跳转记录。在 x86 上,主要利用了 BTS 这个特性。
- Initcall tracer :记录系统在 boot 阶段所调用的 init call
- Mmiotrace tracer :记录 memory map IO 的相关信息
- Power tracer :记录系统电源管理相关的信息
- Sysprof tracer :缺省情况下,sysprof tracer 每隔 1 msec 对内核进行一次采样,记录函数调用和堆栈信息
- Kernel memory tracer :内存 tracer 主要用来跟踪 slab allocator 的分配情况。包括 kfree,kmem_cache_alloc 等 API 的调用情况,用户程序可以根据 tracer 收集到的信息分析内部碎片情况,找出内存分配最频繁的代码片断,等等。
- Workqueue statistical tracer :这是一个 statistic tracer,统计系统中所有的 workqueue 的工作情况,比如有多少个 work 被插入 workqueue,多少个已经被执行等。开发人员可以以此来决定具体的 workqueue 实现,比如是使用
- Event tracer:跟踪系统事件,比如 timer,系统调用,中断等