BUG BUG_ON dump_stack

本文介绍了Linux内核调试中常用的工具和方法,包括BUG()、BUG_ON()和panic()等断言及错误处理函数的使用场景,以及如何利用dump_stack()进行栈信息的输出,帮助开发者在调试过程中快速定位问题。
调试的时候很有用的东西:dump_stack
 
使用前,先在内核配置中把kernel debug选上:
make menuconfig:
kernel hacking-->
kernel debug

 

作用:一些内核调用可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()和BUG_ON()。当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印。为什么这些声明会导致 oops跟硬件的体系结构是相关的。大部分体系结构把BUG()和BUG_ON()定义成某种非法操作,这样自然会产生需要的oops。你可以把这些调用当作断言使用,想要断言某种情况不该发生
if (bad_thing)
BUG();
或者使用更好的形式:
BUG_ON(bad_thing);//BUG_ON是一个函数接口,一般开发人员自己实现相关函数内容,一般用来判断内核是否出现问题,如果参数为真的话,证明内核出现了//bug,打印BUG信息,然后调用PANIC函数,让系统panic。

可以用panic()引发更严重的错误。调用panic()不但会打印错误消息而且还会挂起整个系统。显然,你只应该在极端恶劣的情况下使用它:
if (terrible_thing)
       panic("foo is %ld/n", foo);

 有些时候,你只是需要在终端上打印一下栈的回溯信息来帮助你测试。此时可以使用dump_stack()。它只在终端上打印寄存器上下文和函数的跟踪线索:
if (!debug_check) {
       printk(KERN_DEBUG "provide some information.../n");
       dump_stack();
}


在 Linux 内核中,`dump_stack()` 是一个非常有用的调试函数,用于打印当前任务的调用栈(call stack),帮助开发者了解当前代码执行路径。它常用于内核模块、驱动开发或异常处理中进行问题定位。 --- ## ✅ `dump_stack()` 的作用 - **打印当前调用栈**:显示从当前执行点回溯到用户空间或系统调用入口的所有函数调用路径。 - **辅助调试**:当你在某个函数中发现异常状态或错误条件时,可以通过调用 `dump_stack()` 快速查看调用路径。 - **无需参数**:直接调用即可,不需要任何参数。 --- ## ✅ 使用方式(C 语言) ### 1. 包含头文件 ```c #include <linux/dump_stack.h> ``` ### 2. 调用 `dump_stack()` ```c void my_debug_function(void) { pr_info("Something happened, dumping stack...\n"); dump_stack(); } ``` --- ## ✅ 示例代码 以下是一个简单的内核模块示例,在模块加载时调用 `dump_stack()` 打印调用栈: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/dump_stack.h> static int __init my_module_init(void) { pr_info("my_module loaded\n"); pr_info("Calling dump_stack()\n"); dump_stack(); return 0; } static void __exit my_module_exit(void) { pr_info("my_module unloaded\n"); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple module to demonstrate dump_stack()"); ``` --- ## ✅ 编译与加载模块 ### Makefile 示例: ```makefile obj-m += my_dumpstack.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ``` ### 加载模块并查看日志: ```bash sudo insmod my_dumpstack.ko dmesg | tail -30 ``` 你将在 `dmesg` 输出中看到类似如下的调用栈信息: ``` [ 123.456789] Call Trace: [ 123.456790] dump_stack+0x4c/0x68 [ 123.456791] my_module_init+0x1c/0x50 [my_dumpstack] [ 123.456792] do_one_initcall+0x4e/0x1a0 [ 123.456793] do_init_module+0x1d0/0x1f0 [ 123.456794] load_module+0x1d30/0x21f0 [ 123.456795] __do_sys_init_module+0x1c0/0x220 [ 123.456796] do_syscall_64+0x5b/0xc0 [ 123.456797] entry_SYSCALL_64_after_hwframe+0x44/0xae ``` --- ## ✅ 其他相关函数 | 函数 | 功能 | |------|------| | `dump_stack()` | 打印当前调用栈 | | `show_stack(NULL, NULL)` | 更底层的方式打印调用栈(可用于中断上下文) | | `WARN_ON(condition)` | 如果条件为真,打印警告和调用栈 | | `BUG()` 或 `BUG_ON(condition)` | 强制触发内核 OOPS 并打印栈信息 | --- ## ✅ 使用场景建议 - **内核崩溃或死锁时**:插入 `dump_stack()` 查看当前调用路径。 - **驱动初始化失败**:查看谁调用了驱动加载流程。 - **并发问题调试**:判断是否在非法上下文中被调用(如原子上下文睡眠)。 - **性能瓶颈分析**:虽然不能替代 perf,但可以快速判断热点路径。 --- ## ✅ 注意事项 - `dump_stack()` 不应在频繁路径中使用(如中断处理或软中断中),因为它会影响性能。 - 在原子上下文(atomic context)中使用可能导致内核崩溃。 - 日志输出依赖于 `printk`,请确保你的终端能看到 `dmesg` 输出。 --- ##
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值