内核日志:API 及实现

2026/4/28 0:02:17

内核日志:API 及实现

从内核到用户空间的日志

M. Tim Jones, 独立撰稿人

简介: 在内核开发中,我们通常使用 printk 进行日志。但是您曾经考虑过它的过程,以及内核日志的底层实现吗?本文介绍了内核日志的整个过程,包括 printk 及用户空间日志文件的插入。 发布日期: 2010 年 11 月 09 日

使用日志进行调试的方法由来已久。日志不仅在理解系统的内部操作方面很有用,而且对于通过时间标记的日志中按时间顺序排列的消息所记录的系统活动的计时和关系也非常有用。

本文首先通过介绍用于配置和收集日志信息的应用程序接口(API)来说明了内核的日志(见图 1 关于总结框架和组件的示意图)。然后,本文介绍了日志数据从内核到用户空间的移动过程。最后,本文还介绍了基于内核的日志数据的目标:用户空间中使用 rsyslog 进行日志管理。

图 1. 内核日志生态系统和主要组件

内核 API

内核的日志是通过 printk 函数实现的,它与用户空间对应函数 printf(按格式打印)具有相似的作用。printf 命令在编程语言中已存在很长时间,最近出现是在 C 语言中,但是最早出现可以追溯到 50 年代和 60 年代的 Fortran(PRINT 和

FORMAT 语句)、BCPL(writf 函数;BCPL 是 C 的前身)和 ALGOL 68 语言

(printf 和 putf)。

在内核中,printk(打印内核)可以使用与 printf 函数几乎一样的格式将将格式化消息写入到缓冲区。您可以在 ./linux/include/linux/kernel.h(及其实现 ./linux/kernel/printk.c)中看到 printk 的格式:

int printk( const char * fmt, ... );

这个格式表示的是一个用于定义文本和格式的字符串(类似于 printf),它同时带有一组可变个数参数(由省略号表示 [...])。

内核配置与错误

通过 printk 实现的日志是通过内核配置选项 CONFIG_PRINTK 激活的。虽然

CONFIG_PRINTK 一般都是激活的,但是不包含这个选项的系统对内核的调用会

返回一个 ENOSYS 错误返回值。

在使用 printk 时,您首先会发现的不同点更多是关于协议,而不是功能的。这个特性使用了 C 语言的一种模糊方面来简化消息级别和优先级的规范。内核允许每一个消息根据日志级别(定义不同消息重要必的八种级别之一)来分类。这些级别可以用来判断系统是否不可用(紧急消息)、是否发现严重状况(严重消息)或者是否为简单报告消息。 这个内核代码直接将日志级别定义消息的第一个参数,下面这个例子说明的就是严重消息的定义:

printk( KERN_CRIT \

注意,第一个参数并不一个真正的参数,因为其中没有用于分隔级别

(KERN_CRIT)和格式字符的逗号(,)。KERN_CRIT 本身只是一个普通的字符串(事实上,它表示的是字符串 \;表 1 列出了完整的日志级别清单)。作为预处理程序的一部分,C 会自动地使用一个名为 字符串串联 的功能将这两个字符串组合在一起。组合的结果是将日志级别和用户指定的格式字符串包含在一个字符串中。注意,如果调用者未将日志级别提供给 printk,那么系统就会使用默认值 KERN_WARNING(表示只有 KERN_WARNING 级别以上的日志消息会被记录。)

表 1. 日志级别、标识符和使用方法

标识符 字符串 使用方法

KERN_EMERG <0> KERN_ALERT KERN_CRIT KERN_ERR

<1> <2> <3>

紧急消息(导致系统崩溃) 必须立即处理的错误 严重错误(硬件或软件)

错误状况(一般出现在驱动程序上) 警告状况(可能导致错误) 不是错误,但是一个重要状况 报告消息 仅用于调试的消息 默认内核日志级别

日志行继续(避免增加新的时间截)

KERN_WARNING <4> KERN_NOTICE <5> KERN_INFO

<6>

KERN_DEBUG <7> KERN_DEFAULT KERN_CONT

printk 可以在内核的任意上下文中调用。这个调用从 ./linux/kernel/printk.c 中的 printk 函数开始,它会在使用 va_start 解析可变长度参数之后调用 vprintk(在同

一个源文件)。

日志辅助函数

内核也提供了一些日志辅助函数,它们可以简化日志函数的使用。每一个日志级别都有一个对应的函数,它会扩展为 printk 函数的一个宏。例如,如果要使用

printk 处理 KERN_EMERG 日志级别时,您可以直接使用 pr_emerg。所有宏都已

列在 ./linux/include/linux/kernel.h 文件中。

vprintk 函数执行了许多管理级检查(递归检查),然后获取日志缓冲区的锁

(__log_buf)。接下来,它会对输入的字符串进行日志级别检查; 如果发现日志级别信息,那么对应的日志级别就会被设置。最后,vprintk 会获取当前时间(使


内核日志:API 及实现.doc 将本文的Word文档下载到电脑
搜索更多关于: 内核日志:API 及实现 的文档
相关推荐
相关阅读
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 10

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219