所以我试图找出哪些内核进程正在调用块驱动程序中的某些函数。我认为在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模块时,是否有明显的原因可以保持未定义?
我猜它是因为我使用编译器包含execinfo.h,它驻留在计算机上而不是加载到模块中。
至少可以说,这是我没有受过教育的猜测。
任何人都可以提供帮助,以便在模块中加载回溯功能吗?
感谢您查看此查询。
我正在研究debian。当我取出这样的功能时,模块编译得很好并且几乎完美地工作。
来自ndasusers
答案 0 :(得分:48)
要将堆栈内容和回溯打印到内核日志,请使用内核模块中的dump_stack()
函数。它在linux/kernel.h
中在内核源目录的include文件夹中声明。
答案 1 :(得分:19)
如果您需要保存堆栈跟踪并以某种方式处理其元素,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)
作为“锚点”条目,并仅处理“不低于”的条目。
答案 2 :(得分:0)
我知道这个问题是关于Linux的,但由于它是&#34;回溯内核&#34;的第一个结果,这里还有一些解决方案:
来自/sys/sys/systm.h
的print_backtrace(int count)
。它已在中实施
/sys/kern/kern_debug.c
和/或/sys/platform/pc64/x86_64/db_trace.c
。可以通过搜索在/sys/kern/kern_shutdown.c
中实施的panic
来找到它,如果定义了print_backtrace(6)
并且设置了DDB
则调用trace_on_panic
,这两者都是默认值。
来自/sys/sys/kdb.h
的kdb_backtrace(void)
。同样,通过查看trace_on_panic
实现在{{1}}为真时调用的内容,可以轻松找到它。
转到panic
路线,似乎是panic
。唯一标题提及是db_stack_dump()
, implemented in /sys/ddb/db_output.c
。
答案 3 :(得分:0)
dump_stack()
函数可用于打印堆栈,因此可用于回溯。使用它时要小心,不要把它放在像循环或数据包接收功能这样的重复路径中,它可以填满你的dmesg缓冲区,可能导致嵌入式设备崩溃(内存和cpu较少)。
此功能在linux/kernel.h
中声明。