vlambda博客
学习文章列表

Linux 查看函数参数的若干方法 [二]

上文分别介绍了使用 systemtap, perf-probe 和 bpftrace 来查看函数参数的方法,而本文将通过一个具体的实例,来展示其在 Linux 内核调测中的意义。

依然围绕 pcp high order 这个 patch,原 patch 使用的是 netperf 来测试,理由是网络数据包的收发往往涉及大块内存的分配,那么如何确认这一点呢,即 netperf 确实是否会增加 high order 的页面分配需求?

通过梳理源码,page frame 的分配主要是通过 "get_page_from_freelist" 这个函数进行的,但咱们前面介绍的那些 trace 工具不一定支持这个 probe 点(因为可能被 inline 了),所以得先确认下,比如:

// "-F" 代表 "Show potential probe-able functions"
# perf probe -F 'get_page_from_freelist*'
get_page_from_freelist.part.110

看来是支持的,不过函数名后跟了 ".part + .<some number>" 的 suffix,这是 GCC 的一种编译优化,在准备 inline 一个较大的函数时,将该函数分割,只内联其中的一部分。

静态源码分析判断会调到这个函数,但不一定真的会调到,在开始写 trace 脚本之前,可以用 perf-tools 或者 bcc-tools 中的 funccount 的工具快速验证下:

# ./funccount 'get_page_from_freelist.part.110'

页面分配是一个高频动作,所以如果确实会经过这个函数,那么短时间内就会统计到多次命中。测试结果符合预期,接下来就可以进一步看看,是不是真的有更高 order 的页面分配出现。

在这 3 个 trace 工具,bpftrace 是最快速轻巧的,大部分时候 one-line 搞定,所以笔者首先想到的就是用 bpftrace("order" 是函数的第 2 个参数,参数从 arg0 开始计,所以第 2 个参数是 arg1):

bpftrace -e 'kprobe:get_page_from_freelist { @[arg1] = count(); }' -c 'sleep 5'

先不开 netperf 测一下,结果是这样的:

@[2]: 2
@[1]: 13
@[9]: 13
@[0]: 5439

使用 "netperf -t UDP_STREAM -H localhost -- -m 8192" 后再测一下:

@[9]: 10
@[1]: 13
@[0]: 5426
@[2]: 1228916

order-2 的页面分配明显增加,8192 字节的 payload 加上一些 header,确实需要 16 KB 的页面。

这算是基本验证了使用 netperf 测试 pcp high order 的可行性,但美中不足的是,只能看到数字,不能看到百分比,上面这个不同 order 命中次数差异明显的还好,如果差别不大的,还得自己累加总和后计算比例,着实麻烦。

那就得搬出 perf 来了(虽然需要的步骤多一些),用 perf-probe 给函数参数下探针的方法是这样的("-a" 代表 "add"):

# perf probe -a 'get_page_from_freelist* order'

之后可得到如下的贴心提示:

这时使用 "perf probe -l",就可以看到这个 probe 点,表明真真儿地打上了。那么按照提示,开始一段 5 秒的采样:

perf record -e probe:get_page_from_freelist -aR sleep 5

结束后,得到 "perf.data",我们这里不需要那么细节的信息,可以直接用 "perf report -n --stdio" 将结果打印到终端("-n" 是为了显示数目,否则只显示百分比):