28

所以我试图找出哪些内核进程正在调用块驱动程序中的某些函数。我认为在 C 库中包含 backtrace() 会很容易。但是我无法加载回溯。

我复制了这个示例函数来显示回溯:

http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/063/6391/6391l1.html

所有的编译尝试在某个地方或另一个地方都有错误,即找不到文件或未定义函数。

这是最接近的。

在 Makefile 我放了编译器指令:

 -rdynamic -I/usr/include 

如果我忽略了第二个,-I/usr/include,那么编译器会报告它找不到所需的头文件 execinfo.h。

接下来,在我想要执行回溯的代码中,我从示例中复制了函数:

//trying to include the c backtrace capability
#include <execinfo.h>

void show_stackframe() {
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;

trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
printk(KERN_ERR "[bt] Execution path:\n");
for (i=0; i<trace_size; ++i)
    printk(KERN_ERR "[bt] %s\n", messages[i]);
}
//backtrace function

我稍后在块驱动程序函数中调用了这个函数,错误的第一个迹象发生在该函数中。简单地:

show_stackframe();

所以当我编译它时,出现以下错误:

user@slinux:~/2.6-32$ make -s
Invoking make againt the kernel at /lib/modules/2.6.32-5-686/build
In file included from /usr/include/features.h:346,
        from /usr/include/execinfo.h:22,
        from /home/linux/2.6-32/block/block26.c:49:
/usr/include/sys/cdefs.h:287:1: warning: "__always_inline" redefined
In file included from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc.h:86,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/compiler.h:40,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/stddef.h:4,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/list.h:4,
        from /usr/src/linux-headers-2.6.32-5-common/include/linux/module.h:9,
        from /home/linux/2.6-32/inc/linux_ver.h:40,
        from /home/linux/2.6-32/block/block26.c:32:
/usr/src/linux-headers-2.6.32-5-common/include/linux/compiler-gcc4.h:15:1: warning: this is the location of the previous definition
    /home/linux/2.6-32/block/block26.c:50: warning: function declaration isn’t a prototype
WARNING: "backtrace" [/home/linux/2.6-32/ndas_block.ko] undefined!
WARNING: "backtrace_symbols" [/home/linux/2.6-32/ndas_block.ko] undefined!

注意:block26.c 是我希望从中获取回溯的文件。

当 backtrace 和 backtrace_symbols 被编译到 .ko 模块中时,是否有明显的原因保持未定义?

我猜是因为我使用了编译器 include execinfo.h,它驻留在计算机上并且没有加载到模块中。

至少可以说,这是我没有受过教育的猜测。

任何人都可以提供帮助以在模块中加载回溯功能吗?

感谢您查看此查询。

我正在开发Debian。当我取出函数等时,模块编译得很好,几乎可以完美运行。

来自 ndasusers

4

4 回答 4

52

要打印堆栈内容和内核日志的回溯,请使用dump_stack()内核模块中的函数。它linux/kernel.h在内核源目录的包含文件夹中声明。

于 2011-05-03T06:34:37.753 回答
22

如果您需要保存堆栈跟踪并以某种方式处理其元素,save_stack_trace()或者dump_trace()可能也是一种选择。这些函数分别在<linux/stacktrace.h>和中声明<asm/stacktrace.h>

使用这些并不容易,dump_stack()但如果您需要更大的灵活性,它们可能会有所帮助。

下面是如何save_stack_trace()使用(替换HOW_MANY_ENTRIES_TO_STORE为适合您需要的值,16-32 通常绰绰有余):

unsigned long stack_entries[HOW_MANY_ENTRIES_TO_STORE];
struct stack_trace trace = {
    .nr_entries = 0,
    .entries = &stack_entries[0],

    .max_entries = HOW_MANY_ENTRIES_TO_STORE,

    /* How many "lower entries" to skip. */
    .skip = 0
}; 
save_stack_trace(&trace);

现在stack_entries数组包含适当的调用地址。填充的元素数为nr_entries

还有一件事要指出。如果不希望输出属于 的实现或其自身的堆栈条目save_stack_trace()dump_trace()dump_stack()不同的系统上,此类条目的数量可能会有所不同),如果您使用save_stack_trace(). 您可以将__builtin_return_address(0)其用作“锚”条目并仅处理“不低于”的条目。

于 2011-05-03T12:47:47.863 回答
2

dump_stack()is 函数可用于打印堆栈,因此可用于回溯。在使用它时要小心,不要将它放在循环或数据包接收功能之类的重复路径中,它可能会填充您的 dmesg 缓冲区,这可能会导致嵌入式设备崩溃(内存和 cpu 较少)。

该函数在 linux/kernel.h.

于 2018-04-13T19:40:08.613 回答
2

我知道这个问题是关于 Linux 的,但由于它是“回溯内核”的第一个结果,这里还有一些解决方案:


蜻蜓 BSD

print_backtrace(int count)来自/sys/sys/systm.h. 它在 /sys/kern/kern_debug.c和/或中实现/sys/platform/pc64/x86_64/db_trace.c。可以通过搜索找到panic,实现在 中/sys/kern/kern_shutdown.c,调用print_backtrace(6)ifDDB定义和trace_on_panic设置,都是默认的。


自由BSD

kdb_backtrace(void)来自/sys/sys/kdb.h. panic同样,通过查看实现调用什么时候trace_on_panic是真的很容易找到。


OpenBSD

走这panic条路,它似乎db_stack_dump()/sys/ddb/db_output.c. 唯一提到的标题是/sys/ddb/db_output.h.

于 2018-02-25T02:36:29.643 回答