基于aarch64分析kernel源码 四:printk 内核打印
一、参考
Message logging with printk — The Linux Kernel documentation
如何获得正确的printk格式占位符 — The Linux Kernel documentation
使用printk记录消息 — The Linux Kernel documentation
printk 内核打印 – 人人都懂物联网 (getiot.tech)
内核printk原理介绍 - 知乎 (zhihu.com)
Linux kernel log与调试_内核log_hui_zh的博客-CSDN博客
linux内核日志的存储与读取 | QZJ (eathanq.github.io)
二、printk概述
printk 函数主要做两件事情:
- 将信息记录到 log 中;
- 调用控制台驱动来将信息输出。

从上图可看出,其核心是一个叫做log buffer的循环缓冲区,printk作为生产者将消息存入该缓冲区,右边的log服务模块作为消费者可从log buffer中读取消息。这样设计有以下几个优点:
1、控制台和日志模块初始化前,内核的启动日志可以暂存到log buffer中。待它们初始化完成后,再输出相应信息。
2、在printk log输出太快,而log服务的处理速度不足时,防止log信息丢失。
3、将log输入模块和log输出模块解耦,增加设计的灵活性。
三、log buffer
在内核启动初期,系统内存布局和log buffer大小(cpu核心数等因素决定)不确定,导致无法动态分配内存。为了支持printk,内核通过全局变量方式定义一个log buffer(全局变量被定义在数据段中,会在内核镜像映射过程中被映射),其定义如下:
// kernel/printk/printk.c/* record buffer */
#define LOG_ALIGN __alignof__(unsigned long)
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
#define LOG_BUF_LEN_MAX (u32)(1 << 31)
static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
static char *log_buf = __log_buf;
static u32 log_buf_len = __LOG_BUF_LEN;
当必要信息初始化完成后,在 start_kernel 函数中调用 setup_log_buf(0) 函数动态分配 log buffer。
void __init setup_log_buf(int early)
{……log_buf_len = new_log_buf_len;log_buf = new_log_buf;new_log_buf_len = 0;……
}
四、printk_ringbuffer
log buffer通过数据结构printk_ringbuffer维护其状态信息,其主要成员的关系如下图:

// kernel/printk/printk_ringbuffer.h/** Meta information about each stored message.** All fields are set by the printk code except for @seq, which is* set by the ringbuffer code.*/
struct printk_info {u64 seq; /* sequence number */u64 ts_nsec; /* timestamp in nanoseconds */u16 text_len; /* length of text message */u8 facility; /* syslog facility */u8 flags:5; /* internal record flags */u8 level:3; /* syslog level */u32 caller_id; /* thread id or processor id */struct dev_printk_info dev_info;
};
/** A structure providing the buffers, used by writers and readers.** Writers:* Using prb_rec_init_wr(), a writer sets @text_buf_size before calling* prb_reserve(). On success, prb_reserve() sets @info and @text_buf to* buffers reserved for that writer.** Readers:* Using prb_rec_init_rd(), a reader sets all fields before calling* prb_read_valid(). Note that the reader provides the @info and @text_buf,* buffers. On success, the struct pointed to by @info will be filled and* the char array pointed to by @text_buf will be filled with text data.*/
struct printk_record {struct printk_info *info;char *text_buf;unsigned int text_buf_size;
};/* Specifies the logical position and span of a data block. */
struct prb_data_blk_lpos {unsigned long begin;unsigned long next;
};
/** A descriptor: the complete meta-data for a record.** @state_var: A bitwise combination of descriptor ID and descriptor state.*/
struct prb_desc {atomic_long_t state_var;struct prb_data_blk_lpos text_blk_lpos;
};/* A ringbuffer of "ID + data" elements. */
struct prb_data_ring {unsigned int size_bits;char *data;atomic_long_t head_lpos;atomic_long_t tail_lpos;
};/* A ringbuffer of "struct prb_desc" elements. */
struct prb_desc_ring {unsigned int count_bits;struct prb_desc *descs;struct printk_info *infos;atomic_long_t head_id;atomic_long_t tail_id;atomic_long_t last_finalized_id;
};/** The high level structure representing the printk ringbuffer.** @fail: Count of failed prb_reserve() calls where not even a data-less* record was created.*/
struct printk_ringbuffer {struct prb_desc_ring desc_ring;struct prb_data_ring text_data_ring;atomic_long_t fail;
};
五、日志等级
日志级别的设置,用来控制 printk 打印的这条信息是否在终端上显示的,当日志级别的数值小于控制台级别时,printk 要打印的信息才会在控制台打印出来,否则不会显示在控制台!
在我们内核中一共有8种级别,他们分别为:
// include/linux/kern_levels.h#define KERN_EMERG KERN_SOH "0" /* system is unusable */
#define KERN_ALERT KERN_SOH "1" /* action must be taken immediately */
#define KERN_CRIT KERN_SOH "2" /* critical conditions */
#define KERN_ERR KERN_SOH "3" /* error conditions */
#define KERN_WARNING KERN_SOH "4" /* warning conditions */
#define KERN_NOTICE KERN_SOH "5" /* normal but significant condition */
#define KERN_INFO KERN_SOH "6" /* informational */
#define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
六、控制台级别
// .config#
# printk and dmesg options
#
CONFIG_PRINTK_TIME=y
# CONFIG_PRINTK_CALLER is not set
# CONFIG_STACKTRACE_BUILD_ID is not set
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
// include/linux/printk.h/* printk's without a loglevel use this.. */
#define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT/* We show everything that is MORE important than this.. */
#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */
#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */
#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */
#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up *//** Default used to be hard-coded at 7, quiet used to be hardcoded at 4,* we're now allowing both to be set from kernel config.*/
#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
#define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET
// kernel/printk/printk.cint console_printk[4] = {CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */MESSAGE_LOGLEVEL_DEFAULT, /* default_message_loglevel */CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */
};
EXPORT_SYMBOL_GPL(console_printk);
七、常用的日志函数

相关文章:
基于aarch64分析kernel源码 四:printk 内核打印
一、参考 Message logging with printk — The Linux Kernel documentation 如何获得正确的printk格式占位符 — The Linux Kernel documentation 使用printk记录消息 — The Linux Kernel documentation printk 内核打印 – 人人都懂物联网 (getiot.tech) 内核printk原理…...
机器人中的数值优化(六)—— 线搜索最速下降法
本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,…...
postman调试注意事项
Postman是一个强大的API调试工具,它可以帮助开发人员测试和调试API端点,以确保它们按预期工作。在使用Postman进行接口调试时,以下是一些注意事项和可能出现的问题,以及如何解决这些问题。 确保请求参数正确 在测试API接口时&am…...
【C#】泛型
【C#】泛型 泛型是什么 泛型是将类型作为参数传递给类、结构、接口和方法,这些参数相当于类型占位符。当我们定义类或方法时使用占位符代替变量类型,真正使用时再具体指定数据类型,以此来达到代码重用目的。 泛型特点 提高代码重用性一定…...
CLIP:连接文本-图像
Contrastive Language-Image Pre-Training CLIP的主要目标是通过对比学习,学习匹配图像和文本。CLIP最主要的作用:可以将文本和图像表征映射到同一个表示空间 这是通过训练模型来预测哪个图像属于给定的文本,反之亦然。在训练过程中&#…...
MFC网络编程简单例程
目录 一、关于网络的部分概念1 URL(网址)及URL的解析2 URL的解析3 域名及域名解析3 IP及子网掩码4 什么是Web服务器5 HTTP的基本概念6 Socket库概念7 协议栈8 Socket库收发数据基本步骤 二、基于TCP的网络应用程序三、基于UDP的网络应用程序 一、关于网络的部分概念 1 URL(网址…...
云原生简介 (Cloud Native)
云原生(cloud Native) 云原生的概念诞生于10年前,netflix 在 AWS 上的一次演讲中。有趣的是当初没有明确的定义,现在也没有明确的定义,对不同的人来说,有不同的概念。 概念 云原生:是在云上构…...
【SpringBoot系列】 测试框架之@SpringBootTest的使用
SpringBootTest的详细介绍 SpringBootTest 是 Spring Boot 测试框架中的注解,用于标识一个测试类,以指示该类是一个 Spring Boot 应用程序的测试类。它允许你在测试环境中加载整个 Spring Boot 应用程序上下文,测试应用程序的各种组件、服务…...
【数据结构与算法篇】手撕八大排序算法之交换排序
👻内容专栏: 《数据结构与算法篇》 🐨本文概括:常见交换排序包括冒泡排序与快速排序,本篇讲述冒泡排序与快速排序的思想及实现、复杂度分析。 🐼本文作者: 花 蝶 🐸发布时间&#…...
ArcGIS Pro实践技术应用、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合
GIS是利用电子计算机及其外部设备,采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲,它是在一定的地域内,将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来,达到对地理和属性信息的综合管理。GIS的…...
uniapp 项目实践总结(一)uniapp 框架知识总结
导语:最近开发了一个基于 uniapp 框架的项目,有一些感触和体会,所以想记录以下一些技术和经验,在这里做一个系列总结,算是对自己做一个交代吧。 目录 简介全局文件全局组件常用 API条件编译插件开发 简介 uniapp 是…...
Oracle查看与修改隐藏参数
Oracle查看与修改隐藏参数 查看隐藏参数修改隐藏参数 查看隐藏参数 查看数据库中所有的隐藏参数: SELECT a.ksppinm "Parameter", b.KSPPSTDF "Default Value",b.ksppstvl "Session Value", c.ksppstvl "Instance Value"…...
基于MQTT协议的物联网网关实现远程数据采集及监控
在数字化时代的浪潮中,工业界正面临着前所未有的变革与机遇。而在这场变革中,基于MQTT协议的物联网网关崭露头角,成为连接工业设备、实现远程数据采集与监控的利器。其中,HiWoo Box作为一款出色的工业边缘网关,引领着这…...
服务内部错误: stderr: bash: docker-compose: 未找到命令
报错描述 1Panel在应用商店安装软件失败,重建或者重启报错"服务内部错误: stderr: bash: docker-compose: 未找到命令" 执行命令"docker-compose --version"结果为"Docker Compose version v2.17.2",说明docker-compose已…...
自然语言处理(六):词的相似性和类比任务
词的相似性和类比任务 在前面的章节中,我们在一个小的数据集上训练了一个word2vec模型,并使用它为一个输入词寻找语义相似的词。实际上,在大型语料库上预先训练的词向量可以应用于下游的自然语言处理任务,为了直观地演示大型语料…...
安防监控视频平台EasyCVR视频汇聚平台定制项目增加AI智能算法详细介绍
安防视频集中存储EasyCVR视频汇聚平台,可支持海量视频的轻量化接入与汇聚管理。平台能提供视频存储磁盘阵列、视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联、H.265自动转码等功能。为了便…...
VB个人邮件处理系统设计与实现
简述 当今世界电子邮件已经是网络生活中不可或缺的,相信每个认知网络的人都会有一个或多个自己的电子邮箱,人们通过电子邮件进行通信和交流,许多商家和组织机构也用电子邮件进行各种商业活动和业务联系,毫无疑问,电子邮件已经逐渐开始取代普通的信件,成为为主流的信件交流…...
第一章辩证唯物论,考点七思维导图
逻辑框架 考点七思维导图:...
Python入门教程 - 基本函数(四)
目录 一、什么是函数 二、自定义函数并使用它 一、什么是函数 前面我们学习了像input()、print()、type()等等,他们都是函数。这些其实是由Python内部帮我们定义好的。我们直接用就可以了。 关于函数,除了用内部定义好的,我们也可以自己定…...
[PyTorch][chapter 53][Auto Encoder 实战]
前言: 结合手写数字识别的例子,实现以下AutoEncoder ae.py: 实现autoEncoder 网络 main.py: 加载手写数字数据集,以及训练,验证,测试网络。 左图:原图像 右图:重构图像 ----main----- 每轮训…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
