Linux 内核启动过程中的日志输出阶段分析
Linux 内核启动过程中的日志输出阶段分析一、引言为什么要理解内核启动日志Linux 内核的启动过程是一个高度复杂且有序的初始化流程。在这个过程中内核会输出大量日志信息这些日志对于系统运维人员、驱动开发者以及内核开发者来说是诊断启动故障、理解硬件初始化顺序的重要依据。许多人只会在系统无法启动时才想起查看dmesg输出但实际上日志输出本身也遵循着严格的阶段性规律。本文将从基础概念出发带领你逐步理解内核在启动过程中日志输出是如何从无到有、从简单到丰富演进的。我们会涉及到 printk 机制、控制台初始化以及日志缓冲区的管理。## 二、基础概念printk 与日志级别### 2.1 什么是 printk在 Linux 内核中printk是内核态最常用的日志输出函数类似于用户态的printf。它允许内核在任意位置输出信息包括中断上下文、进程上下文等。c// 基础 printk 使用示例printk(Hello, Kernel World!\n);printk(KERN_INFO This is an informational message\n);printk(KERN_ERR This is an error message\n);### 2.2 日志级别Log Level每个 printk 消息都带有一个日志级别用于表示消息的严重程度。内核通过比较消息级别与当前控制台的日志级别console_loglevel来决定是否将消息输出到控制台。常见的日志级别从高到低| 宏定义 | 级别值 | 含义 ||--------|--------|------|| KERN_EMERG | 0 | 紧急情况系统不可用 || KERN_ALERT | 1 | 需要立即处理 || KERN_CRIT | 2 | 临界条件 || KERN_ERR | 3 | 错误条件 || KERN_WARNING | 4 | 警告条件 || KERN_NOTICE | 5 | 普通但重要的条件 || KERN_INFO | 6 | 信息性消息 || KERN_DEBUG | 7 | 调试级别的消息 |### 2.3 日志输出流程当 printk 被调用时内核会执行以下步骤1. 格式化消息字符串2. 将消息写入环形缓冲区ring buffer3. 检查消息级别是否 console_loglevel4. 如果是则立即输出到当前控制台5. 唤醒可能等待日志输出的进程如klogd## 三、启动阶段的日志输出演变### 3.1 早期启动阶段无控制台输出在 x86 架构下内核解压完成后会进入start_kernel()函数。在启动的最早期阶段大约是setup_arch()之前控制台硬件如串口、VGA 文本模式尚未初始化。此时所有 printk 输出都会被写入 __log_buf内核日志缓冲区但不会显示在任何物理设备上。c// 早期启动阶段的典型代码arch/x86/kernel/head_64.S 中// 此时只能使用早期的非常规输出方式例如通过 I/O 端口直接写串口mov $0x3f8, %dx // COM1 端口地址mov $K, %alout %al, %dx // 直接输出到串口不经过 printk 机制### 3.2 控制台初始化阶段日志开始可见当内核执行到console_init()函数时它会遍历所有注册的控制台驱动程序并激活第一个可用的控制台。这个阶段通常发生在start_kernel()的中期。控制台初始化的顺序决定了哪些日志会先出现在屏幕上。常见的控制台类型包括-VGA 文本控制台典型的 PC 显示器输出-串口控制台通过 RS-232 或 USB 串口输出-earlyprintk一种早期的调试输出机制c// 一个简化的控制台初始化流程伪代码void __init console_init(void){ // 1. 注册内置控制台 con_init(); // 初始化 VGA 控制台 // 2. 激活第一个控制台 // 之后所有 printk 输出都会同时写入缓冲区并显示到控制台 register_console(vt_console_driver); // 3. 打印初始化完成消息 printk(KERN_INFO Console: colour dummy device 80x25\n);}### 3.3 完整初始化阶段多控制台与日志管理在start_kernel()的最后阶段内核会启动init进程并切换到用户空间。此时日志系统已经完整运行包括- 环形缓冲区ring buffer已完全初始化-/proc/kmsg和/dev/kmsg设备文件可用- syslog 系统调用可用## 四、代码示例模拟日志输出阶段### 4.1 示例一使用 Python 模拟日志缓冲区的环形结构为了帮助你理解内核日志缓冲区的管理方式我们编写一个简单的 Python 程序来模拟环形缓冲区的工作原理。python#!/usr/bin/env python3模拟 Linux 内核日志缓冲区ring buffer的行为演示 printk 消息如何被存储和读取class KernelLogBuffer: 内核日志缓冲区模拟类 def __init__(self, size1024): self.buffer [None] * size # 固定大小的环形缓冲区 self.size size self.write_pos 0 # 当前写入位置 self.read_pos 0 # 当前读取位置 self.msg_count 0 # 消息计数 def printk(self, level, message): 模拟内核的 printk 函数 # 构造日志条目包含级别和内容 log_entry f[{level}] {message} # 写入环形缓冲区 self.buffer[self.write_pos] log_entry self.write_pos (self.write_pos 1) % self.size self.msg_count 1 # 如果缓冲区写满覆盖最旧的记录 if self.write_pos self.read_pos: self.read_pos (self.read_pos 1) % self.size # 返回消息是否应该输出到控制台 # 假设控制台日志级别为 6KERN_INFO console_loglevel 6 return level console_loglevel def read_logs(self, count10): 读取最近的日志条目 logs [] pos self.read_pos for _ in range(min(count, self.msg_count)): if self.buffer[pos] is not None: logs.append(self.buffer[pos]) pos (pos 1) % self.size return logs# 模拟内核启动过程if __name__ __main__: log_buf KernelLogBuffer(size32) # 阶段1: 早期启动控制台未初始化 print( 阶段1: 早期启动 - 日志只写入缓冲区 ) log_buf.printk(7, Early boot: CPU initialization) # KERN_DEBUG log_buf.printk(6, Early boot: Memory detection) # KERN_INFO # 阶段2: 控制台初始化 print(\n 阶段2: 控制台初始化 - 日志开始输出 ) log_buf.printk(5, Console: Initializing VGA console) # KERN_NOTICE log_buf.printk(4, Console: Registered device driver) # KERN_WARNING # 阶段3: 完整启动 print(\n 阶段3: 完整启动 - 正常日志输出 ) log_buf.printk(3, Mounting root filesystem) # KERN_ERR log_buf.printk(2, Starting init process) # KERN_CRIT # 读取并打印缓冲区状态 print(\n缓冲区中的日志:) for log in log_buf.read_logs(10): print(f {log}) print(f\n总共写入 {log_buf.msg_count} 条日志) print(f缓冲区已用空间: {len([x for x in log_buf.buffer if x is not None])}/{log_buf.size})### 4.2 示例二使用 Python 分析 dmesg 输出在实际的 Linux 系统中我们可以通过dmesg命令获取内核日志。下面的 Python 脚本演示了如何解析这些日志并分析启动阶段。python#!/usr/bin/env python3分析 dmesg 输出识别内核启动阶段需要 root 权限或 /var/log/dmesg 文件import refrom collections import defaultdictdef parse_dmesg_logs(log_file/var/log/dmesg): 解析 dmesg 日志文件识别不同启动阶段 参数: log_file: dmesg 日志文件路径 返回: 按阶段分组的日志字典 phases defaultdict(list) current_phase unknown # 定义阶段的识别模式 phase_patterns { early_boot: [ rLinux version, rCommand line, rBIOS-provided physical RAM map ], console_init: [ rConsole: colour, rconsole \[tty, rserial8250: ttyS ], device_init: [ rpci_bus, rata[0-9], rusb [0-9] ], filesystem: [ rVFS: Mounted root, rEXT4-fs, rkjournald ], init_done: [ rFreeing unused kernel memory, rinit started ] } try: with open(log_file, r, errorsignore) as f: for line in f: # 检测阶段切换 for phase, patterns in phase_patterns.items(): for pattern in patterns: if re.search(pattern, line, re.IGNORECASE): current_phase phase break # 提取时间戳如果有 timestamp_match re.match(r\[\s*(\d\.\d)\], line) timestamp timestamp_match.group(1) if timestamp_match else N/A # 存储日志 phases[current_phase].append({ timestamp: timestamp, message: line.strip() }) except FileNotFoundError: print(f错误: 找不到日志文件 {log_file}) print(请尝试运行: dmesg /tmp/dmesg.txt 并修改脚本路径) return None return phasesdef print_phase_analysis(phases): 打印各阶段的分析报告 if not phases: return total_lines sum(len(lines) for lines in phases.values()) print(f总日志条数: {total_lines}) print(- * 60) for phase, logs in phases.items(): print(f\n阶段: {phase} ({len(logs)} 条日志)) print(- * 40) # 显示前3条和后2条日志作为示例 if len(logs) 5: for log in logs[:3]: print(f [{log[timestamp]}] {log[message][:80]}) print(f ... (中间 {len(logs)-5} 条省略) ...) for log in logs[-2:]: print(f [{log[timestamp]}] {log[message][:80]}) else: for log in logs: print(f [{log[timestamp]}] {log[message][:80]})if __name__ __main__: # 分析当前系统的 dmesg 日志 phases parse_dmesg_logs() if phases: print_phase_analysis(phases)## 五、高级话题自定义日志输出与调试技巧### 5.1 动态调整控制台日志级别在内核运行时可以通过/proc/sys/kernel/printk文件动态调整日志级别。文件中包含四个数字$ cat /proc/sys/kernel/printk7 4 1 7分别代表1. 控制台日志级别console_loglevel2. 默认消息日志级别default_message_loglevel3. 最低控制台日志级别minimum_console_loglevel4. 默认控制台日志级别default_console_loglevel修改方法bash# 只显示 KERN_WARNING (4) 及以上级别的消息echo 4 4 1 7 /proc/sys/kernel/printk### 5.2 使用 earlyprintk 进行早期调试当系统在启动早期崩溃时常规控制台可能尚未工作。此时可以使用earlyprintk内核参数bash# 在 GRUB 启动参数中添加earlyprintkserial,ttyS0,115200这样可以在控制台初始化之前将日志直接输出到串口。## 六、总结通过本文的学习我们深入理解了 Linux 内核启动过程中日志输出的演变规律1.早期阶段日志仅写入内核缓冲区不显示到物理设备2.控制台初始化第一个控制台被激活日志开始可见3.完整阶段多控制台支持用户空间工具可读取日志掌握这些知识有助于我们在系统启动失败时通过分析dmesg输出来定位问题。无论是硬件初始化失败、驱动加载异常还是文件系统挂载错误启动日志都能提供关键的线索。最后建议读者在实验环境中多观察不同内核版本的启动日志尝试调整printk级别这样能够获得更深刻的理解。记住每一次内核启动都是一次精彩的初始化交响乐而日志就是这场交响乐的乐谱。

相关新闻

openclaw自动写代码由于脱敏机制误判导致代码不可用

openclaw自动写代码由于脱敏机制误判导致代码不可用

问题描述:借助openclaw辅助编写脚本或工程代码时,偶尔遇到敏感信息脱敏为***的场景,且反复沟通后,无法完成修正。代码如下:api_key os.getenv("OPENAI_API_KEY") base_url os.getenv("OPENAI_BASE_UR…

2026/7/31 12:06:16阅读更多 →
基于MCU微控制器的冰箱压缩机系统解决方案

基于MCU微控制器的冰箱压缩机系统解决方案

在智能冰箱的整体架构中,压缩机是决定设备制冷性能、能耗水平与运行稳定性的核心机械电控部件,它的控制精度直接影响冰箱的能效等级、静音效果与使用寿命。随着家电变频智能化升级,传统控制方案已难以适配高端冰箱的节能、低噪、稳定运行需求…

2026/7/31 12:06:16阅读更多 →
【人大金仓KingbaseES安装教程】最新图文详解(附安装包)

【人大金仓KingbaseES安装教程】最新图文详解(附安装包)

前言 在国产数据库浪潮席卷各行各业的今天,人大金仓KingbaseES安装教程已成为众多DBA和运维人员最常搜索的技术文档之一。作为中国较早具备完整自主知识产权的关系型数据库,KingbaseES凭借其出色的Oracle兼容性和企业级稳定性,正在党政、金融…

2026/7/31 12:06:16阅读更多 →
扣子错误处理节点配置错误导致任务丢失?立即执行这6步紧急修复清单!

扣子错误处理节点配置错误导致任务丢失?立即执行这6步紧急修复清单!

更多请点击: https://codechina.net 第一章:扣子错误处理节点配置错误导致任务丢失?立即执行这6步紧急修复清单! 当扣子(Dify / Coze 类低代码编排平台)的错误处理节点(Error Handler Node&…

2026/7/31 19:44:21阅读更多 →
FeatureToggle核心组件解析:从AlwaysOn到SqlFeatureToggle全攻略

FeatureToggle核心组件解析:从AlwaysOn到SqlFeatureToggle全攻略

FeatureToggle核心组件解析:从AlwaysOn到SqlFeatureToggle全攻略 【免费下载链接】FeatureToggle Simple, reliable feature toggles in .NET 项目地址: https://gitcode.com/gh_mirrors/fe/FeatureToggle FeatureToggle是一个为.NET应用程序设计的简单而可靠…

2026/7/31 19:44:21阅读更多 →
如何在Apple Silicon上部署HVI-CIDNet-LOLv1-fp32?Swift实战教程

如何在Apple Silicon上部署HVI-CIDNet-LOLv1-fp32?Swift实战教程

如何在Apple Silicon上部署HVI-CIDNet-LOLv1-fp32?Swift实战教程 【免费下载链接】HVI-CIDNet-LOLv1-fp32 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/HVI-CIDNet-LOLv1-fp32 HVI-CIDNet-LOLv1-fp32是一款基于Apple MLX框架的低光图像增强…

2026/7/31 19:44:21阅读更多 →
AI驱动的零售增长飞轮:从客流预测到动态定价,9个可立即复用的算法模型架构

AI驱动的零售增长飞轮:从客流预测到动态定价,9个可立即复用的算法模型架构

更多请点击: https://intelliparadigm.com 第一章:AI驱动的零售增长飞轮:核心范式与商业逻辑演进 传统零售的增长模型正经历根本性重构——从线性投入产出关系,转向由数据闭环、智能决策与用户反馈持续强化的动态飞轮系统。AI不再…

2026/7/31 19:44:21阅读更多 →
《基于plc的喷泉控制系统设计》13(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

《基于plc的喷泉控制系统设计》13(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

《基于plc的喷泉控制系统设计》13(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码 本商品为电子程序资料 商品包含内容: ①花式喷泉博途PLC与HMI仿真工程 (博途V15.1) 一份; ②花式喷泉配套有IO点表PLC接…

2026/7/31 19:44:21阅读更多 →
专业级Windows安卓应用安装解决方案:APK Installer深度技术解析与实战指南

专业级Windows安卓应用安装解决方案:APK Installer深度技术解析与实战指南

专业级Windows安卓应用安装解决方案:APK Installer深度技术解析与实战指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在当今移动应用生态蓬勃发展的时…

2026/7/31 19:42:21阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/30 15:03:16阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/31 17:41:43阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/30 15:13:02阅读更多 →
物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:40阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:41阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/31 0:49:33阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/31 5:08:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/31 16:02:17阅读更多 →