内核里常用宏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
相关推荐
啊吧怪不啊吧3 小时前
UU远程协助迎来升级!第一期更新实测
运维·服务器·远程工作
C_心欲无痕8 小时前
ts - tsconfig.json配置讲解
linux·前端·ubuntu·typescript·json
冰西瓜6009 小时前
国科大2025操作系统高级教程期末回忆版
linux
HIT_Weston10 小时前
93、【Ubuntu】【Hugo】搭建私人博客:面包屑(一)
linux·运维·ubuntu
cuijiecheng201810 小时前
Linux下Beyond Compare过期
linux·运维·服务器
喵叔哟10 小时前
20.部署与运维
运维·docker·容器·.net
HIT_Weston10 小时前
92、【Ubuntu】【Hugo】搭建私人博客:侧边导航栏(六)
linux·运维·ubuntu
CodeAllen嵌入式10 小时前
Windows 11 本地安装 WSL 支持 Ubuntu 24.04 完整指南
linux·运维·ubuntu
期待のcode10 小时前
前后端分离项目 Springboot+vue 在云服务器上的部署
服务器·vue.js·spring boot
AI 智能服务11 小时前
第6课__本地工具调用(文件操作)
服务器·人工智能·windows·php