BUG_ON()、panic()、dump_stack()几种内核调试手段

Linux内核有一些方法可以用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()和BUG_ON()。

当被调用的时候,它们会引发oops,导致栈的回溯和错误信息的打印。这些声明会导致 oops跟硬件的体系结构是相关的。大部分体系结构把BUG()和BUG_ON()定义成某种非法操作,这样自然会产生需要的oops。你可以把这些调用当作断言使用,想要断言某种情况不该发生:

if (bad_thing)
BUG(); //需要linux 内核开启General setup->Configure standard kernel features->BUG() support

或者使用更好的形式:

BUG_ON(bad_thing); 

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

if (terrible_thing)panic("foo is %ld\n", foo);  

有些时候,你只是需要在终端上打印一下栈的回溯信息来帮助你测试。此时可以使用dump_stack()。它只在终端上打印寄存器上下文和函数的跟踪线索:

if (!debug_check) {printk(KERN_DEBUG "provide some information...\n");dump_stack();
}

举个例子程序

这个例子是参考了别人的代码,我按照这个代码执行下给大伙看看。通过触发proc下的文件来触发不同的执行函数。

/*************************************************************************> File Name: pro.c> Author:> Mail:> Created Time: 2020年03月07日 星期六 11时19分38秒************************************************************************/#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include <asm/types.h>// Module to make a read entry in the proc file system.
// Module to write a command line calculatorMODULE_LICENSE("GPL");
MODULE_AUTHOR("329410527@qq.com");#define MY_PROC_ENTRY "bugon-test"struct proc_dir_entry *proc;
int len;
char *msg = NULL;
#define DATA_SIZE 1024 // We can keep 1024 bytes of data with us./** Function to write to the proc. Here we free the old data, and allocate new space and copy the data to* that newly allocated area.*/#define MY_BUG_ON 1
#define MY_BUG 2
#define MY_DUMPSTACK 3
#define MY_PANIC 4
static int param = 100;/*文件的写函数*/
static ssize_t my_proc_write(struct file *filp, const char __user * buffer, size_t count, loff_t *pos)
{char *str;str = kmalloc((size_t) count, GFP_KERNEL);if (copy_from_user(str, buffer, count)) {kfree(str);return -EFAULT;}sscanf(str, "%d", &param);printk("param has been set to %d\n", param);kfree(str);switch (param) {case MY_BUG_ON:BUG_ON(param);break;case MY_BUG:BUG();break;case MY_DUMPSTACK:dump_stack();break;case MY_PANIC:panic("I am panicking, Why? -- you told so");break;default:printk("unknow param...\n");}return count;
}
/*读proc文件*/
ssize_t my_proc_read(struct file *filp,char *buf,size_t count, loff_t *offp )
{int err;char *data = PDE_DATA(file_inode(filp));if ((int) (*offp) > len) {return 0;}printk(KERN_INFO "Reading the proc entry, len of the file is %d", len);if(!(data)) {printk(KERN_INFO "NULL DATA");return 0;}if (count == 0) {printk(KERN_INFO "Read of size zero, doing nothing.");return count;} else {printk(KERN_INFO "Read of size %d", (int) count);}count = len + 1; // +1 to read the \0err = copy_to_user(buf, data, count); // +1 for \0printk(KERN_INFO "Read data : %s", buf);*offp = count;if (err) {printk(KERN_INFO "Error in copying data.");} else {printk(KERN_INFO "Successfully copied data.");}return count;
}/*proc文件系统的fops*/
struct file_operations proc_fops = {.read = my_proc_read,.write = my_proc_write,
};int create_new_proc_entry(void) {int i;char *DATA = "Hello People";len = strlen(DATA);/*申请内存空间*/msg = kmalloc((size_t) DATA_SIZE, GFP_KERNEL); // +1 for \0if (msg != NULL) {printk(KERN_INFO "Allocated memory for msg");} else {return -1;}/*把字符串拷贝到msg*/strncpy(msg, DATA, len+1);for (i=0; i < len +1 ; i++) {printk(KERN_INFO "%c", msg[i]);}/*建立proc文件系统*/proc = proc_create_data(MY_PROC_ENTRY, 0666, NULL, &proc_fops, msg);if (proc) {return 0;}return -1;
}int __init proc_bug_on_init (void)
{if (create_new_proc_entry()){return -1;}return 0;
}void __exit proc_bug_on_cleanup(void) {remove_proc_entry(MY_PROC_ENTRY, NULL);
}module_init(proc_bug_on_init);
module_exit(proc_bug_on_cleanup);

Makefile文件:

PWD=$(shell pwd)
VER=$(shell uname -r)
KERNEL_BUILD=/lib/modules/$(VER)/build
$(info $(PWD))
$(info $(VER))
ifneq ($(KERNELRELEASE),)
obj-m := pro.o
else
PWD  := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
install:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules_install
clean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
endif

执行make命令后生成文件

weiqifa0@weiqifa-System-Product-Name:/ssd/weiqifa0/linux-c/pro-module$ make
/ssd/weiqifa0/linux-c/pro-module
5.0.0-23-generic
make -C /lib/modules/5.0.0-23-generic/build M=/ssd/weiqifa0/linux-c/pro-module modules
make[1]: Entering directory '/usr/src/linux-headers-5.0.0-23-generic'
/usr/src/linux-headers-5.0.0-23-generic
5.0.0-23-genericCC [M]  /ssd/weiqifa0/linux-c/pro-module/pro.oBuilding modules, stage 2.
/usr/src/linux-headers-5.0.0-23-generic
5.0.0-23-genericMODPOST 1 modulesCC      /ssd/weiqifa0/linux-c/pro-module/pro.mod.oLD [M]  /ssd/weiqifa0/linux-c/pro-module/pro.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.0.0-23-generic'
weiqifa0@weiqifa-System-Product-Name:/ssd/weiqifa0/linux-c/pro-module$

执行加载模块

sudo insmod pro.ko

执行触发bugon操作 sudo echo 1 > /proc/bugon-test

[930845.292938] ------------[ cut here ]------------
[930845.292939] kernel BUG at /ssd/weiqifa0/linux-c/pro-module/pro.c:57!
[930845.292942] invalid opcode: 0000 [#2] SMP NOPTI
[930845.292944] CPU: 2 PID: 12116 Comm: echo Tainted: G      D    OE     5.0.0-23-generic #24~18.04.1-Ubuntu
[930845.292944] Hardware name: System manufacturer System Product Name/PRIME Z370-P II, BIOS 0602 03/14/2019
[930845.292946] RIP: 0010:my_proc_write.cold.3+0x75/0x77 [pro]
[930845.292947] Code: 36 01 d6 eb 1d 0f 0b 83 f8 03 74 11 83 f8 04 75 e6 48 c7 c7 c0 f0 6e c0 e8 2c 8b fa d5 e8 66 2b 92 d6 48 89 d8 e9 8a fe ff ff <0f> 0b 48 c7 c7 76 f1 6e c0 31 db 49 c7 c4 9e f1 6e c0 e8 bf 36 01
[930845.292948] RSP: 0018:ffffb3e60a44fe50 EFLAGS: 00010246
[930845.292949] RAX: 0000000000000000 RBX: 0000000000000002 RCX: 0000000000eec799
[930845.292949] RDX: 0000000000eec798 RSI: ffff907726aa7040 RDI: ffff907726403c80
[930845.292950] RBP: ffffb3e60a44fe68 R08: 0000000000027040 R09: ffffffffc06ee1c8
[930845.292950] R10: ffffd547606a6f80 R11: ffffb3e60a44fcc0 R12: ffff90771a9be310
[930845.292951] R13: 000055852def8410 R14: 000055852def8410 R15: ffff907683c1f300
[930845.292952] FS:  00007f6b9f9de580(0000) GS:ffff907726a80000(0000) knlGS:0000000000000000
[930845.292952] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[930845.292953] CR2: 00007f6b9f87f6f0 CR3: 000000014850a004 CR4: 00000000003606e0
[930845.292953] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[930845.292954] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[930845.292954] Call Trace:
[930845.292957]  proc_reg_write+0x3e/0x60
[930845.292959]  __vfs_write+0x1b/0x40
[930845.292960]  vfs_write+0xb1/0x1a0
[930845.292961]  ksys_write+0x5c/0xe0
[930845.292962]  __x64_sys_write+0x1a/0x20
[930845.292964]  do_syscall_64+0x5a/0x120
[930845.292966]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[930845.292967] RIP: 0033:0x7f6b9f8ff024
[930845.292968] Code: 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b3 0f 1f 80 00 00 00 00 48 8d 05 b9 d3 0d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53
[930845.292968] RSP: 002b:00007fff9b739518 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[930845.292969] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f6b9f8ff024
[930845.292970] RDX: 0000000000000002 RSI: 000055852def8410 RDI: 0000000000000001
[930845.292970] RBP: 000055852def8410 R08: 00007f6b9f9d9580 R09: 00007f6b9f9de580
[930845.292971] R10: 00007f6b9f9d6ca0 R11: 0000000000000246 R12: 00007f6b9f9d7760
[930845.292971] R13: 0000000000000002 R14: 00007f6b9f9d8560 R15: 00007f6b9f9d7960
[930845.292972] Modules linked in: pro(OE) tcp_diag inet_diag snd_hda_codec_realtek snd_hda_codec_generic amdgpu ledtrig_audio chash amd_iommu_v2 gpu_sched intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_hdmi aesni_intel snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event snd_rawmidi i915 snd_seq aes_x86_64 crypto_simd snd_seq_device cryptd glue_helper snd_timer kvmgt eeepc_wmi intel_cstate nls_iso8859_1 vfio_mdev asus_wmi intel_rapl_perf input_leds radeon wmi_bmof snd joydev sparse_keymap mxm_wmi mdev vfio_iommu_type1 ttm vfio soundcore kvm irqbypass drm_kms_helper drm mei_me i2c_algo_bit mei fb_sys_fops syscopyarea sysfillrect sysimgblt mac_hid acpi_pad sch_fq_codel parport_pc ppdev lp parport ip_tables x_tables autofs4 hid_generic usbhid hid nvme r8169 ahci realtek nvme_core libahci wmi video [last unloaded: pro]
[930845.292992] ---[ end trace 622fbd2856be7806 ]---
[930845.292993] RIP: 0010:my_proc_write.cold.3+0x75/0x77 [pro]
[930845.292994] Code: 36 01 d6 eb 1d 0f 0b 83 f8 03 74 11 83 f8 04 75 e6 48 c7 c7 c0 f0 6e c0 e8 2c 8b fa d5 e8 66 2b 92 d6 48 89 d8 e9 8a fe ff ff <0f> 0b 48 c7 c7 76 f1 6e c0 31 db 49 c7 c4 9e f1 6e c0 e8 bf 36 01
[930845.292994] RSP: 0018:ffffb3e60893fe50 EFLAGS: 00010246
[930845.292995] RAX: 0000000000000000 RBX: 0000000000000002 RCX: 0000000000e7affd
[930845.292996] RDX: 0000000000e7affc RSI: ffff907726ba7040 RDI: ffff907726403c80
[930845.292996] RBP: ffffb3e60893fe68 R08: 0000000000027040 R09: ffffffffc06ee1c8
[930845.292997] R10: ffffd547607934c0 R11: 0000000000000001 R12: ffff90771e4d37e8
[930845.292997] R13: 00005585c2683050 R14: 00005585c2683050 R15: ffff907721602200
[930845.292998] FS:  00007f6b9f9de580(0000) GS:ffff907726a80000(0000) knlGS:0000000000000000
[930845.292998] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[930845.292999] CR2: 00007f6b9f87f6f0 CR3: 000000014850a004 CR4: 00000000003606e0
[930845.292999] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[930845.293000] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400

其他的操作也是一样。

大家在调试过程中,可以试试这个方法。在自己的异常代码加上后,如果有其他调用导致。就可以看到是谁的调用导致的。

我们看看BUG_ON()定义的位置

kernel/include/asm-generic/bug.h
/** Don't use BUG() or BUG_ON() unless there's really no way out; one* example might be detecting data structure corruption in the middle* of an operation that can't be backed out of.  If the (sub)system* can somehow continue operating, perhaps with reduced functionality,* it's probably not BUG-worthy.** If you're tempted to BUG(), think again:  is completely giving up* really the *only* solution?  There are usually better options, where* users don't need to reboot ASAP and can mostly shut down cleanly.*/
#ifndef HAVE_ARCH_BUG
#define BUG() do { \printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \barrier_before_unreachable(); \panic("BUG!"); \
} while (0)
#endif#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
#endif

里面的注释写的很明白,如果你有其他的办法,建议不要使用BUG_ON()。

  回复「 篮球的大肚子」进入技术群聊

回复「1024」获取1000G学习资料

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wordvba编程代码大全_这几本基础编程书籍一定要看

程序员书库(ID&#xff1a;OpenSourceTop) 编译书单来自&#xff1a;https://simpleprogrammer.com/best-programming-books-2019/关于程序员类的技术书籍有很多&#xff0c;但是往往没有时间阅读&#xff0c;下面的这些书籍&#xff0c;由John Sonmez精选&#xff0c;可以帮助…

经典DP

1.背包问题 &#xff08;1&#xff09;01背包 从n个重量和价值分别为wi,vi的物品&#xff0c;从中选出不超过W的物品&#xff0c;每种物品仅有一件&#xff0c;求所有方案中V的最大值。 最朴素最简单也最费时的方法&#xff1a;O(2^n) int rec(int i,int j)//从第i个开始挑选总…

C语言、嵌入式重点知识:回调函数

前言 上文分享了一个专用的双链表的基本操作示例&#xff1a;双链表的操作示例&#xff08;附代码&#xff09;这里提到了一个关键词&#xff1a;专用。与专用对应的词是通用。我们从字面上可以很容易理解这两个词&#xff0c;专用就是针对特定情况的&#xff0c;特点就是很有局…

今天我勇敢的点就一个gpio口

现在已经三月份了&#xff0c;时间过得超快&#xff0c;早上起来打开电脑&#xff0c;有点不习惯&#xff0c;微信群唧唧歪歪的那些股神今天不知为什么安静了。我喜欢看大家热闹的样子&#xff0c;更喜欢热闹的时候给我们发几个红包。我记得2015年&#xff0c;股市非常好&#…

数据结构(4)

文章目录栈与队列栈队列![在这里插入图片描述](https://img-blog.csdnimg.cn/20200301182116946.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzY2Mzc4MA,size_16,color_FFFFFF,t_70)栈与队列 栈 ha…

写一个公用的gpio口驱动

因为项目需要控制的GPIO口比较多&#xff0c;如果每个GPIO口都写一个驱动就显得比骄麻烦&#xff0c;所以就写了一个通用的GPIO口驱动。只要dts里面配置好设备GPIO相关信息就可以自动加载了。可以很充分的体现多个设备一个驱动的优良性。dts文件gpio_rs485: gpio_rs485 {status…

数据结构(5)

文章目录各种算法选择排序插入排序希尔排序***快速排序***归并排序二分查找各种算法 def bubble_sort(alist):"""冒泡排序"""n len(alist)for j in range(n-1):count 0for i in range(0, n-1-j):# 班长从头走到尾if alist[i] > alist[i1]:a…

大神们都应该去哪里工作?

接上一篇文章。文中提到我认识了一个做嵌入式的大神&#xff0c;技术真的非常厉害。我们在调试过程中&#xff0c;遇到问题&#xff0c;他总是能告诉我们排查的手段&#xff0c;而且针对一个问题&#xff0c;他能想到几种不同的解决方案。嵌入式驱动跟其他软件有点不一样&#…

大华管理平台用户名_智能财务引领商业与管理变革——浙大EMBA首席财务官研习社走进大华股份...

杭商传媒记者 周 珂/文 徐青青/摄编辑 何影丹当前经济环境和市场需求瞬息万变&#xff0c;企业竞争日益激烈&#xff0c;盈利持续下降&#xff0c;产品、服务同质化严重&#xff0c;这不仅对业务部门提出了挑战&#xff0c;也对传统的财务管理产生了巨大的冲击。财务不能高…

【深度】韦东山:一文看尽 linux对中断处理的前世今生

作者&#xff1a;韦东山前言&#xff1a;本文&#xff0c;4200字&#xff0c;研究代码花了一天&#xff0c;写出来花了一天&#xff1b;录视频估计又得花半天&#xff1b;真怀念以前简单粗暴的生活啊&#xff1a;拿起话筒就录视频&#xff0c;先画好图&#xff1f;那是不需要的…

数据结构(6)二叉树

文章目录二叉树二叉树三种遍历二叉树知中及先或后序&#xff0c;求二叉树二叉树 class Node(object):""""""def __init__(self, item):self.elem itemself.lchild Noneself.rchild Noneclass Tree(object):"""二叉树"&qu…

鼠标中间无法打开新标签_还记得鼠标有几个键?Win10环境鼠标中键的妙用

大家经常使用鼠标&#xff0c;但有多少人还能意识到&#xff0c;其实鼠标是有三个键的&#xff1f;除了常用的左键右键&#xff0c;鼠标中间的滚轮也可以按下去&#xff0c;然而鼠标的这个中键&#xff0c;却日常坐冷板凳&#xff0c;几乎被人所遗忘。其实&#xff0c;鼠标中键…

找不到问题的核心,你永远解决不了问题。

上学那会儿&#xff0c;我是个数学常拿60分的人&#xff08;满分150分&#xff09;&#xff0c;我却喜欢做几何题。根据已知的条件&#xff0c;推导出所需的其他条件&#xff0c;所有需要的条件得出后&#xff0c;再根据正确的公式算出所求的值。这个不断求解的过程其实挺有意思…

浏览器访问pdf 的url怎么加密_怎么解决加密的pdf文件?

加密版的PDF文件我们每次打开时都需要输入密码才能进行阅读&#xff0c;而且一般不能直接进行复制和打印&#xff0c;这样会非常的麻烦。那如果我门想要解决这一问题呢就要将pdf文件的密码进行解除&#xff0c;可是如果是平民的我们不会解决怎么办呢&#xff1f;毕竟我们又不是…

Linux Storage入门学习

前言本文大量代码基于linux 0.11&#xff0c;因为早期linux的版本更加适合初学者入门。虽然代码比较早&#xff0c;但是不妨碍我们学习Linux Storage的精髓。一、hello world1.1 Demo#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include&l…

地铁客流检测训练问题记录

一 报错&#xff1a; File "/home/jz/py-faster-rcnn/tools/../lib/datasets/pascal_voc.py", line 183, in _load_pascal_annotation tree ET.parse(filename) File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1182, in parse tree.parse(sou…

记一次和摄像头的摩擦经历

因为时间的原因&#xff0c;这次点亮摄像头的时间特别短&#xff0c;昨天下午模组到公司&#xff0c;今天下午点亮。几个人一起调试&#xff0c;发现的问题也很多&#xff0c;今天下午发现有一个怀疑的问题&#xff0c;我马上驱车几十公里去模组厂调试&#xff0c;回来的时候&a…

声明为指针,定义为数组,声明为数组,定义为指针

之前写发的那篇指针和数组的文章&#xff0c;有网友评论觉得不是很舒服&#xff0c;我自己看了&#xff0c;觉得很不满意。所以想再写写&#xff0c;尽量把这个东西讲清楚。#定义为数组&#xff0c;声明为指针1.c中#include "stdio.h" char array[] "abcd"…

f2fs存储结构初探

前言学习文件系统的第一步&#xff0c;先搞清楚文件系统在设备上的存储结构&#xff0c;先来简单了解一下。F2FS空间布局图和描述选自《F2FS技术拆解》https://mp.weixin.qq.com/s/k1ibtWF_TRQi8wbqUGjMrgF2FS空间布局F2FS空间布局整个存储空间被划分为6个区域&#xff1a;超级…

net.conn read 判断数据读取完毕_高并发:缓存模式以及缓存的数据一致性

缓存由于其高性能&#xff0c;支持高并发的特性&#xff0c;在高并发的项目中不可或缺。被大家广泛使用的有Redis&#xff0c;Memcached等。本文主要探讨几种常见的缓存的读写模式&#xff0c;以及如何来保证缓存和数据库的数据一致性。这里大家可以关注一下我的个人专栏《PHP进…