谢欢《Linux内核tracers的实现原理与应用》课程精彩答疑
Posted 宋宝华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谢欢《Linux内核tracers的实现原理与应用》课程精彩答疑相关的知识,希望对你有一定的参考价值。
作者简介
谢欢,大家可以叫我Jeff, 我目前就职于某国际知名linux发行版开源公司, 热衷于linux内核。我平时把linux内核源码当小说一样阅读学习,也一直把能给linux社区贡献更多有质量的代码而努力。
今年10月中旬,我向Linux内核社区提交了一个关于tracing 的patchset. tracing 的 Maintainer steve 和kprobe的maintainer Masami都非常感兴趣。
学员:Jeff老师,请教一下,您课程的理论和方法在arm+android环境下适用吗,实验是不是可以玩
Jeff老师:都可以玩,具体实现会跟架构不同有所区别,x86搞会了,其他的架构可以去套
学员:function graph trace挂的第二个钩子函数 怎么返回到 parent函数的呢,这个返回值不是被覆盖了吗这块没交代
Jeff老师:是的,这个地方没有交代,因为你会在kretprobe章节那里看到类似的逻辑,我当时是考虑从全局看不想讲两次一样的,如果想了解的话,parent被覆盖之前已经被保存了,在调用第二个钩子函数(return_to_handler)之后,会返回到parent处,代码如下:
SYM_FUNC_START(return_to_handler)
subq $24, %rsp
/* Save the return values */
movq %rax, (%rsp)
movq %rdx, 8(%rsp)
movq %rbp, %rdi
call ftrace_return_to_handler
movq %rax, %rdi <rax是ftrace_return_to_handler的返回值,也是parent的地址>
movq 8(%rsp), %rdx
movq (%rsp), %rax
addq $24, %rsp
JMP_NOSPEC rdi
Jeff老师与学员日常对话截取:
Jeff老师:其实讲解基本的使用不太费时间的,主要是讲解底层原理,确实要花不少时间,我自己也是一个刨根问底的人
学员:基本使用网上也可以搜到一大堆教程,但是原理的东西才是难得地方。有老师带着学,我们可以事半功倍,搞懂了原理,再去使用工具,更加得心应手了
老师如果有精力,也可以出一些内核子系统的实现讲解,就像ftrace这种讲法就挺好
Jeff老师:我是准备之后讲解block子系统的,从文件系统到多队列调度器以及块设备驱动,一个个来
学员:jeff老师,我想打印这个函数里面的vq->last_used_index,用kprobe可以吗?
void *virtqueue_get_buf_ctx(struct virtqueue*_vq, unsigned int *len,
void **ctx)
structvring_virtqueue *vq = to_vvq(_vq);
…
last_used =(vq->last_used_idx & (vq->vring.num - 1));
…
Jeff老师:可以,和函数参数相关的变量,直接用kprobe_event就可以
借助gdb 算偏移还算挺方便,如果你觉得麻烦,可以自己写一个kprobe模块插进去 。
学员:怎样用trace如何打出io从insert到complete中的函数栈
Jeff老师:这个有挺多方法,就看怎么灵活运用,例如:
echo 0 > ./tracing_on
echo 1 >./events/block/block_bio_queue/enable
echo traceon >./events/block/block_bio_queue/trigger
echo 1 >./events/block/block_rq_insert/enable
echo traceon >./events/block/block_rq_insert/trigger
echo 1 >./events/block/block_rq_complete/enable
echo traceoff > ./events/block/block_rq_complete/trigger
echo function > current_tracer
Jeff老师主动拉高学员的学习热情和讨论欲:
Jeff老师:我最近想到一个idea,不再局限于跟踪函数,跟踪struct page,跟踪struct bio,跟踪struct task_struct,任何对象都可以动态跟踪,正在准备提个大补丁到社区去,看能不能合并进去。
学员甲:这个厉害了
学员乙:这个功能overhead高吗?
学员丙:比较有意思。大致原理是啥,访问内存的时候触发异常?
Jeff老师:到时候看我补丁,你会觉得简单的想哭
最新补丁进展:
https://lore.kernel.org/all/20211129164951.220511-1-xiehuan09@gmail.com/
学员自悟一刻:
“看到trace_event 有点晕了,我理解trace_event是不是就是一种静态的预埋的点, 当enable + filter后,输出信息到buffer中去?本身的实现和之前的ftrace其实没有关系?然后 老师说的 trace_event要多次展开, 各种unset 和define, 为何要多次呢?这里有点晕啊。
其实第一节课的内容能听懂,后面就都好懂了, 第四课的trace_event 我后来自己搜了一些文章看了一遍,再结合视频又听了一遍,能大致听懂 trace_event 的实现原理和逻辑,只是还是有刚才上面的疑问。本质上还是自己基础不扎实。
阅码场有人投稿写了trace_event的,我也搜到了,《LinuxTraceEvent - 我见过的史上最长宏定义》
还是偏源码解析的,就是上来给你一坨代码,讲一遍过程,但是为何要这么做,就像老师讲的kprobe,原来是走int3,现在利用ftrace的5个nop,可以更方便使用,这个有前后关系的,其实就很好理解。
我好像悟了, TRACE_EVENT这一系列undef和define, 就是事先 给你用宏定义了好了若干个代码模板, 然后你用一个 宏定义 -TRACE_EVENT, 在经过不同模块的(子系统时),帮你生成对应逻辑的代码, 或者说,是内核约定了一个套路,各个模块 都按这个套路写, 然后帮你生成代码,说穿了就是一个静态代码生成器。”
trace视频课程订阅二维码:
以上是关于谢欢《Linux内核tracers的实现原理与应用》课程精彩答疑的主要内容,如果未能解决你的问题,请参考以下文章
早鸟价今晚结束:Linux内核tracers的实现原理与应用