我正在写这篇文章,而不是沮丧 - 但谁知道呢,也许也有办法......
我想分析一下 ALSA 中的一个函数会发生什么,比如说snd_pcm_readi
;为此,假设我准备了一个小testprogram.c
的 ,我有这个:
void doCapture() {
ret = snd_pcm_readi(handle, buffer, period_size);
}
这个函数的问题是它最终(应该)挂接到snd_pcm_readi
共享系统库中/usr/lib/libasound.so
;我相信从那里开始,ioctl
它会以某种方式snd_pcm_read
在内核模块中进行通信/lib/modules/$(uname -r)/kernel/sound/core/snd-pcm.ko
——并且最终应该与.ko
作为特定声卡驱动程序的任何内核模块进行通信。
现在,有了上述组织,我可以执行以下操作:
valgrind --tool=callgrind --toggle-collect=doCapture ./testprogram
...然后kcachegrind callgrind.out.12406
确实揭示了snd_pcm_readi
,libasound.so
和 an之间的关系ioctl
(我无法获得相同的信息来显示callgrind_annotate
)-因此在某种程度上涵盖了用户空间;但仅此而已。此外,它生成一个调用图,即函数之间的一般调用者/被调用者关系(可能通过每个函数按计划工作的样本/滴答计数)。
但是,我想得到的是类似于 Linuxftrace
跟踪器的输出function_graph
,它提供了跟踪内核函数的时间戳进入和退出...来自ftrace 的示例:添加函数图跟踪器的文档 [LWN.net]:
$ cat /sys/kernel/debug/tracing/trace
# tracer: function_graph
#
# TIME CPU DURATION FUNCTION CALLS
# | | | | | | | |
2105.963678 | 0) | mutex_unlock() {
2105.963682 | 0) 5.715 us | __mutex_unlock_slowpath();
2105.963693 | 0) + 14.700 us | }
2105.963698 | 0) | dnotify_parent() {
(注意:较新的ftrace
文档最初似乎没有显示时间戳function\_graph
,只有持续时间 - 但我认为仍然可以修改它)
使用ftrace
, 可以进行过滤,因此只能跟踪给定内核模块中的函数 - 所以在我的情况下,我可以添加声卡驱动程序snd-pcm.ko
以及任何.ko
模块的函数,并且我会在内核空间中找到我感兴趣的任何内容. 但是,我失去了到用户空间程序的链接(除非我明确地printf
这样/sys/kernel/debug/tracing/trace_marker
做,或者trace_printk
从用户空间.c
文件中执行)
最终,我想要的是有可能指定一个可执行文件,也可能是库文件和内核模块 - 并获得一个带时间戳的函数图(每个函数带有缩进/嵌套的入口和出口),就像ftrace
提供的那样。有没有类似的东西的替代品?(注意我可以在没有函数退出的情况下生活 - 但我真的很想有时间戳的函数条目)
作为一个 PS:似乎我实际上找到了符合描述的东西,即fulltrace
应用程序/脚本:
fulltrace 跟踪 ELF 程序的执行,提供其用户空间、库和内核函数调用的完整跟踪作为输出。...
(先决条件)以下内核配置选项及其依赖项必须设置为启用 (=y):FTRACE、TRACING_SUPPORT、UPROBES、UPROBE_EVENT、FUNCTION_GRAPH_TRACER。
听起来很完美 - 但问题是,我在 Ubuntu 11.04 上,虽然2.6.38
幸运的是这个内核已经CONFIG_FTRACE=y
启用 - 它/boot/config-`uname -r`
甚至没有提到UPROBES
:/ 因为我想避免进行内核黑客攻击,不幸的是我不能使用这个脚本...
(顺便说一句,如果 UPROBES 可用,(据我所知)在符号地址上设置一个跟踪探测(从 say 获得objdump -d
),然后输出再次转到/sys/kernel/debug/tracing/trace
- 所以使用 UPROBES 可以实现一些自定义解决方案,即使没有fulltrace
脚本)_
因此,为了缩小我的问题范围 - 是否有一种解决方案,可以同时进行用户空间(包括共享库)和内核空间“函数图”跟踪,但UPROBES
内核中哪些地方不可用?