linux 内核warn_on/Bug_on

1,warn_on() 

warn_on() 是 Linux 内核中用于报告潜在问题或警告的宏。与 bug_on() 不同,bug_on() 通常用于报告严重错误,其触发往往会导致内核Oops或panic,而 warn_on() 则用于报告不太严重的、可能只是潜在问题或预期外情况的情况。它的触发通常不会立即导致系统崩溃,而是记录警告信息并打印 call trace,让开发者或管理员了解发生了什么。

warn_on() 的工作原理(简化版):

  1. 条件判断warn_on(condition) 宏会被展开为类似 if (unlikely(condition)) 的代码。

  2. 触发警告:如果 condition 为真,代码会执行到一个内核函数,通常是 WARN_ON() 宏或相关的函数(如 printk() 加上特定的格式和调试信息)。

  3. 打印信息:这个函数会打印出警告信息,包括:触发警告的文件名和行号。内核版本信息。Call Trace: 显示触发警告的函数调用链。这是 warn_on() 提供的最有价值的信息之一。其他可能的调试信息(如寄存器状态,取决于内核配置)。

  4. 继续执行:与 bug_on() 不同,warn_on() 通常会打印信息后继续执行下一条指令。这允许系统在记录问题后尝试从警告状态恢复(尽管有时警告也预示着严重问题)。

举例:

#include <linux/kernel.h>
#include <linux/module.h>void my_driver_function(struct my_data *data) {// ... 一些代码 ...// 检查指针是否为 NULL,如果是则发出警告WARN_ON(!data); // 在 my_driver.c:100// ... 更多代码 ...
}static int __init my_driver_init(void) {// ... 初始化代码 ...my_driver_function(NULL); // 故意传递 NULL 来触发警告// ... 更多初始化代码 ...return 0;
}static void __exit my_driver_exit(void) {// ... 清理代码 ...
}module_init(my_driver_init);
module_exit(my_driver_exit);

当 my_driver_function(NULL) 被调用时,WARN_ON(!data) 的条件为真(因为 data 是 NULL),就会触发警告。

假设这个警告发生在 CPU 0 上,内核环缓冲区 (dmesg) 中可能会看到类似如下的输出(具体格式可能因内核版本和配置略有不同):

[ 123.456789] WARNING: CPU: 0 PID: 1234 at drivers/my_driver/my_driver.c:100 my_driver_function+0x5a/0x120 (not tainted)

[ 123.456789] Hardware name: ...

[ 123.456789] Call Trace:

[ 123.456789] dump_stack+0x4c/0x73

[ 123.456789] ? my_driver_function+0x5a/0x120

[ 123.456789] ? WARN_ON+0x7b/0x90

[ 123.456789] my_driver_function+0x5a/0x120 [my_driver]

[ 123.456789] my_driver_init+0x40/0x100 [my_driver]

[ 123.456789] do_one_initcall+0x130/0x170

[ 123.456789] kernel_init_freeable+0x130/0x170

[ 123.456789] ? kernel_init+0x10/0x10

[ 123.456789] kernel_init+0x10/0x170

[ 123.456789] ret_from_fork+0x22/0x30

[ 123.456789] ---[ end trace 123456789abcdef ]---

2,bug_on()

bug_on() 触发时如何打印 call trace(调用跟踪)。

bug_on() 是 Linux 内核中用于检测和报告严重错误的宏。它的作用类似于 C 语言中的 assert(), 但专门用于内核环境。当传递给 bug_on() 的条件为真(非零)时,它会触发一个内核 Oops(类似于用户空间的段错误),并打印出非常有用的调试信息,其中就包括 call trace。

bug_on() 的工作原理(简化版):

  1. 条件判断bug_on(condition) 宏会被展开为类似 if (unlikely(condition)) { ... } 的代码。
  2. 触发错误:如果 condition 为真,代码会执行到一个内核函数,通常是 BUG() 或相关的宏/函数。
  3. 打印信息:这个函数会打印出错误信息,包括:
    • 触发 BUG 的文件名和行号。
    • 内核版本信息。
    • Call Trace: 这是最关键的部分,它显示了触发 BUG 的函数调用链。
    • CPU 信息、寄存器状态等(取决于内核配置和 Oops 类型)。
  4. 处理后果:通常会导致进程终止(如果是进程中的错误)或系统进入 Oops 状态,可能需要手动重启。在启用 CONFIG_PANIC_ON_OOPS=y 的情况下,可能会直接触发 panic() 导致系统崩溃。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h> // for pr_info// 假设这个函数不应该被调用
static void do_something_undefined(void)
{// 触发 bug_on: 假设某个不应该为真的条件发生了// 这里我们强制让它为真来演示int should_be_false = 1;// 当 should_be_false 为真时,bug_on 会触发// 内核宏通常写成 bug_on(should_be_false)// 为了演示,我们假设它触发了// --- 以下是模拟的 bug_on 触发后的内核输出 ---// 文件: my_module.c// 函数: do_something_undefined// 行号: 15// --- 内核实际打印信息 ---// BUG: Badness at my_module.c:15 in do_something_undefined()// Modules linked in: my_module// Pid: 1234, comm: insmod Tainted: G        W ...// RIP: 0010:[do_something_undefined+0x10/0x30]// Code: Bad RIP value.// RSP: 0000:ffffc900003aefb8 EFLAGS: 00010206// RAX: 0 RAX: 0 RAX: 0 RAX: 0// ...// Call Trace://  my_function+0x20/0x50 [my_module]//  another_function+0x15/0x40 [my_module]//  my_init+0x25/0x80 [my_module]//  do_one_initcall+0x80/0x300//  kernel_init_freeable+0x130/0x170//  ? kthreadd+0x70/0x70//  kernel_init+0x10/0x100//  ret_from_fork+0x22/0x30// --- 内核实际打印信息结束 ---pr_info("This line won't be reached if bug_on triggers.\n");
}static int my_function(void)
{pr_info("Inside my_function\n");do_something_undefined(); // 调用那个会触发 bug_on 的函数return 0;
}static int another_function(void)
{pr_info("Inside another_function\n");return my_function(); // 调用 my_function
}static int __init my_init(void)
{pr_info("Initializing my module\n");return another_function(); // 调用 another_function
}static void __exit my_exit(void)
{pr_info("Exiting my module\n");
}module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A module demonstrating bug_on call trace");

异常打印如下: 

BUG: Badness at my_module.c:15 in do_something_undefined()
Modules linked in: my_module
...
Pid: [PID], comm: [Command that loaded the module, e.g., insmod]
RIP: [Instruction pointer at the bug_on location]
Code: [Opcode at RIP]
RSP: [Stack pointer]
...
Call Trace:
 do_something_undefined+0x10/0x30 [my_module]
 my_function+0x20/0x50 [my_module]
 another_function+0x15/0x40 [my_module]
 my_init+0x25/0x80 [my_module]
 do_one_initcall+0x80/0x300
 kernel_init_freeable+0x130/0x170
 ? kthreadd+0x70/0x70
 kernel_init+0x10/0x100
 ret_from_fork+0x22/0x30

如何获取 bug_on 的输出

  1. 串口 (Serial Console): 如果你的系统通过串口连接,错误信息通常会直接输出到串口。
  2. tty 控制台: 如果 bug_on 发生在直接连接的显示器上,信息会打印在那里。
  3. dmesg 命令: 在 bug_on 发生后,即使系统可能已经挂起或重启,你通常也可以使用 dmesg 命令来查看内核环缓冲区(kernel ring buffer)中的消息,包括 Oops 信息和 Call Trace。
  4. /var/log/kern.log 或 /var/log/syslog: 在某些系统上,kern.log 或 syslog 文件会记录内核消息,包括 Oops。

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

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

相关文章

SQL输出20个9

在SQL Server中要输出20个连续的9&#xff0c;可以使用以下几种方法&#xff1a; 使用REPLICATE函数重复生成字符&#xff1a; SELECT REPLICATE(9, 20) AS Result 2. 使用UNION ALL联合查询生成多行&#xff1a; SELECT 9 AS Number FROM (VALUES (1),(1),(1),(1),(1),(1),…

懒人云电脑方案:飞牛NAS远程唤醒 + 节点小宝一键唤醒、远程控制Windows!

后台高频问题解答&#xff1a; “博主&#xff0c;飞牛NAS能定时开关机了&#xff0c;能不能让它顺便把家里Windows电脑也远程唤醒控制&#xff1f;最好点一下就能连&#xff0c;不用记IP端口那种&#xff01;” 安排&#xff01;今天这套方案完美实现&#xff1a; ✅ 飞牛NAS…

Linux特殊符号

1 管道符| 管道符号 | 用于将一个命令的输出作为另一个命令的输入。这种机制允许将多个命令组合在一起&#xff0c;形成一个数据处理链&#xff0c;每个命令处理前一个命令的输出&#xff0c;从而实现复杂的数据处理任务。示例 # 查询/var/log目录下所有的log文件,并进行分页…

初识Docker:容器化技术的入门指南

初识Docker&#xff1a;容器化技术的入门指南 一、Docker是什么&#xff1a;容器化技术的核心概念二、Docker的核心优势2.1 环境一致性2.2 高效部署与快速迭代2.3 资源利用率高 三、Docker的安装与基本使用3.1 安装Docker3.2 Docker基本概念3.3 第一个Docker容器体验 四、Docke…

商务风企业公司推广培训计划PPT模版分享

商务风企业公司推广培训计划PPT模版分享&#xff1a;商务培训推广计划PPT模版https://pan.quark.cn/s/063282eaf739 第1套PPT模版&#xff0c;绿橙配色&#xff0c;几何图形拼接背景&#xff0c;有中英文标题和占位文本。 第2套PPT模版是黑金高端商务风格&#xff0c;有汇报人…

深入理解Nginx:详尽配置手册

Nginx是一款高性能的HTTP和反向代理服务器&#xff0c;广泛应用于负载均衡、缓存和Web服务器等场景。随着互联网应用的快速发展&#xff0c;掌握Nginx的配置和优化技巧显得尤为重要。在本篇文章中&#xff0c;我们将深入探讨Nginx的配置&#xff0c;帮助你更好地理解和使用这款…

每日leetcode

1572. 矩阵对角线元素的和 - 力扣&#xff08;LeetCode&#xff09; 题目 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3], …

Server 9 ,在 VMware 虚拟机上安装 Windows 系统完整指南

目录 前言 一、准备工作 1.1 准备安装文件 1.2 安装VMware软件 1.3 创建新的虚拟机 1.4 开启虚拟机 二、注意事项 2.1 调整硬件设置 2.2 启动顺序配置 2.3 固件类型选择 2.4 安全启动配置 三、安装优化 3.1 安装VMware Tools 3.2 系统更新与激活 四、更多操作 ​…

最终章:终焉之塔 · 前端之道

第一章&#xff1a;HTML基石现实的骨架 第二章&#xff1a;CSS秘典 色彩与布局的力量 第三章&#xff1a;JavaScript引擎 行为之火 第四章&#xff1a;DOM迷宫 掌控页面之心 第五章&#xff1a;异步幻境 时间与数据的秘密 第六章&#xff1a;事件风暴 用户的意志 第七章&a…

详解 .net9 内置 Lock 对象,更加现代化和灵活可控的锁对象

.NET 9 引入了全新的 System.Threading.Lock 类型&#xff0c;作为更现代、类型安全且具备递归支持的同步原语。与传统的基于 Monitor.Enter/lock(obj) 的方式不同&#xff0c;Lock 是一个具体的类&#xff0c;提供了更灵活的 API 和结构化编程模型。 Lock 类 Lock 是一个具体…

python几行命令实现快速打包apk

1. ​​环境准备​ sudo apt update sudo apt install -y python3-pip git zip unzip openjdk-17-jdk sudo apt-get install -y autoconf automake libtool pip install kivy buildozer cython2. ​​项目配置​ 在项目目录中初始化Buildozer&#xff1a; buildozer init这会…

实时数仓和离线数仓的区别是什么?企业如何选择合适的数仓架构?

实时数仓和离线数仓的区别是什么&#xff1f;企业如何选择合适的数仓架构&#xff1f; 时数仓和离线数仓都是数据仓库的不同类型&#xff0c;用于存储和管理企业的数据&#xff0c;但它们在数据处理和使用的时间、速度以及用途方面有明显的区别。 在介绍实时数仓之前&#xf…

Docker Desktop for Windows 系统设置说明文档

1. 文档概述 本文档旨在详细说明 Docker Desktop for Windows 应用程序中“设置 (Settings)”界面下的所有可配置选项及其子选项。对于每个配置项&#xff0c;我们将提供其功能描述、推荐配置&#xff08;如适用&#xff09;以及相关注意事项&#xff0c;帮助用户更好地理解和…

精准监测,健康无忧--XC3576H工控主板赋能亚健康检测仪

在快节奏的现代生活中&#xff0c;亚健康问题逐渐成为困扰人们健康的隐形杀手。疲劳、失眠、免疫力下降等问题频发&#xff0c;却往往因难以察觉而延误调理。智能亚健康检测仪通过高科技手段&#xff0c;帮助用户实时了解身体状况&#xff0c;提前预警潜在健康风险。 其核心功能…

SBT开源构建工具

SBT 的多元定义与核心解释 SBT&#xff08;Simple Build Tool&#xff09;是专为 Scala 和 Java 项目设计的开源构建工具&#xff0c;基于 Scala 语言开发&#xff0c;提供依赖管理、编译、测试、打包等全流程支持。其核心特点包括&#xff1a; 核心功能与特性&#xff1a; …

npm run build后将打包文件夹生成zip压缩包

安装依赖 npm install archiver --save-dev准备compress.js文件 const fs require(fs); const archiver require(archiver);const sourceDir ./dist; //替换为你的文件夹路径 const outputZip ./dist.zip;console.log(开始压缩); const output fs.createWriteStream(ou…

力扣 215 .数组中的第K个最大元素

文章目录 题目介绍题解 题目介绍 题解 法一&#xff1a;基于快速排序的选择方法 以中间元素pivot为基准进行排序后&#xff0c;右指针 r 的位置就是最终全部排序好后pivot的位置&#xff0c;然后去左边或右边递归寻找第k个位置&#xff08;答案&#xff09;的元素。 代码如下…

CentOS 7.0重置root密码

文章目录 版本&#xff1a;CentOS 7.0内核版本&#xff1a;CentOS Linux, with Linux 3.10.0-123.el7.x86_64 服务器重启后&#xff0c;等待进入上述页面&#xff0c;按⬆⬇键&#xff0c;中断正常启动。在此页面按E&#xff0c;进入编辑模式 继续按⬇&#xff0c;找到linux16…

Linux之高效文本编辑利器 —— vim

目录 一、vim的基本概念 二、Vim 的三种基本模式 1. 命令模式&#xff08;Command Mode&#xff09; 2. 插入模式&#xff08;Insert Mode&#xff09; 3. 底行模式&#xff08;Last Line Mode&#xff09; 模式切换方法 IDE例子&#xff1a; 三、vim的基本操作 进入vim…

【STM32】HAL库 之 CAN 开发指南

基于stm32 f407vet6芯片 使用hal库开发 can 简单讲解一下can的基础使用 CubeMX配置 这里打开CAN1 并且设置好波特率和NVIC相关的配置 波特率使用波特率计算器软件 使用采样率最高的这段 填入 得到波特率1M bit/s 然后编写代码 环形缓冲区 #include "driver_buffer.h&qu…