内核里常用宏BUG_ON/WARN_ON/WARN_ONCE

一、背景

内核代码里经常能看到一些用于检查一些条件的宏,如BUG_ON,WARN_ON等,这些宏除了直观的说明条件应该或者不应该被满足以外,还能方便我们进行规范的打印,让代码更加简洁,也同时满足的一些基本的要求,如在内核代码里进行打印时不建议直接使用printk,需要使用dev_printk或者至少得用pr_xx这样的打印宏。你若使用printk来进行打印输出的时候,如果用./scripts/checkpatch.pl来扫描你的改动的patch的话,如果发现是直接使用printk的话,checkpatch.pl的检查脚本会报出一个警告的。

这篇博客里,我们一次介绍一下这些基本的宏。

二、BUG/BUG_ON宏

我们搜索BUG_ON宏可以搜到,它是分为可以是ARCH代码来实现,也可以不用ARCH代码用公共的代码来实现:

如上图可以看到BUG_ON就是判断入参的条件,如果入参的条件是true,就调用BUG宏来触发panic。

CONFIG_BUG默认情况下就是打开的:

在没有定义arch的BUG_ON函数时,就用公共代码的BUG_ON实现。

可以看到是有有些arch下实现自己的BUG_ON的,搜索HAVE_ARCH_BUG_ON就可以搜到:

如mips平台的BUG_ON实现:

三、WARN_ON,WARN_ON_ONCE,WARN_ONCE宏

3.1 WARN_ON的实现

WARN_ON的下面的定义也是被包在一般都开的CONFIG_BUG宏里的:

常见的arm64平台和x86平台也都是用的上图里的定义。

我们进一步看__WARN宏的实现,__WARN宏根据有没有定义__WARN_FLAGS的情况,

来进行的定义:

而__WARN_FLAGS在x86和arm64平台都有相关定义:

我们追一下arm64平台的也就是上图里的__BUG_FLAGS是如何实现的,如上图看到__BUG_FLAGS使用了ASM_BUG_FLAGS,ASM_BUG_FLAGS定义如下:

可以看到上面图里红色框出的部分,也就是用了brk汇编指令,传入的是BUG_BRK_IMM,定义及如下:

3.2 WARN_ON_ONCE和WARN_ONCE的区别

WARN_ON_ONCE和WARN_ONCE在内核代码里大量使用,它们俩是有区别的,虽然区别并不复杂,但是却很有用,且容易被忽视。

WARN_ON_ONCE的定义如下:

它是无法输入自定义的字符串的。

而WARN_ONCE则不同,可以输入自定义的字符串:

这个区别很关键,有时候就需要定义自己的日志内容。

3.3 WARN_ONCE如何确保只打印一次

接着上面分析的WARN_ONCE宏来看一下WARN_ONCE宏所调用的DO_ONCE_LITE_IF宏是如何实现的:

如上图可以看到DO_ONCE_LITE_IF宏使用了__ONCE_LITE_IF宏来判断是否已经打印了一次。

而__ONCE_LITE_IF宏声明了一个static的bool类型的变量,这样就可以保留之前是否已经打印一次的状态了。

3.4 如何清楚打印了一次的标记

可以从上面 3.3 的分析里可以看到,在声明用于判断是否打印一次的变量时,用得是__section(".data.once")的段,这个为什么要用这个段呢,因为这个段可以让系统针对这些WARN_ONCE的标记的变量统一进行一些批处理。

下图里的clear_warn_once_set函数就是对该.data.once段的所有标记位进行清除:

而clear_warn_once_set被集成进clear_warn_once_fops后,

最后暴露出debugfs的用户态可以进行控制的节点:

有关的可以清楚WARN_ONCE标记的命令如下:

bash 复制代码
echo 1 > /sys/kernel/debug/clear_warn_once
相关推荐
技术小李...15 分钟前
docker下mysql更改密码后WordPress提示无法连接数据库问题
运维·docker·容器
hhcgchpspk25 分钟前
一次msf免杀渗透入门实践
linux·经验分享·网络安全·系统安全·渗透·msf
Focussend智能化营销32 分钟前
2026破局:以营销自动化成熟度Macom模型为鞍,驰骋增长新赛道!
运维·自动化
wanhengidc1 小时前
什么是裸金属服务器
运维·服务器·科技·智能手机·云计算
我命由我123451 小时前
Python Flask 开发 - Flask 快速上手(Flask 最简单的案例、Flask 处理跨域、Flask 基础接口)
服务器·开发语言·后端·python·学习·flask·学习方法
小白勇闯网安圈1 小时前
Vmware的Ubuntu构建极简版Linux发行版
linux
刘某的Cloud1 小时前
shell脚本-read-输入
linux·运维·bash·shell·read
莫问前程_满城风雨1 小时前
verilog 可变范围的bit选择
运维·服务器·verilog
AEMC马广川1 小时前
能源托管项目中“企业认证+人才证书”双轨评分策略分析
大数据·运维·人工智能·能源
无锡耐特森1 小时前
CANopen转Profinet网关:小设备撬动自动化产线大效率
运维·自动化