当前位置: 首页 > news >正文

Linux Kernel Core API:printk

简单介绍

printk()是Linux Kernel最广为认知的函数之一。它是我们打印消息的标准工具,通常也是追踪和调试的最基本方法。printk()是基于printf(3)实现的,有如下功能差异:

  1. printk()消息可以指定级别
  2. 格式字符串虽然很大程度上与C99基本兼容,但不遵守完全相同的规范。它有一些扩展和限制(如:没有%n或浮点转换说明符)。

所有的printk()消息会被打印到内核的一个通过/dev/kmsg暴露给用户空间的环形日志缓存。使用dmesg命令可以读取这个日志缓存。

printk()典型使用:

printk(KERN_INFO "Message: %s\n", arg);

其中KERN_INFO是日志级别(注意,它与格式字符串连在一起,日志级别不是一个单独的参数)。

一条日志能不能打印出来、是不是立即打印出来、是不是同行打印出来等,受两方面影响:

  • 日志记录方式。就是你使用哪个接口输出日志、使用哪个级别输出日志。
  • printk当前控制。

printk实现

日志级别说明消息的重要性。内核决定是否立即显示某条消息(打印它到当前控制台)取决于这条消息的log level和当前控制台console_loglevel(一个内核变量):

  • 消息的优先级越高表示日志级别的值越低。
  • 优先级高于console_loglevel的消息将被打印到console。
  • 如果消息省略了log level,这条消息将按KERN_DEFAULT级别打印。

日志级别

如下表,printk()消息有8个级别(0-7),对应每个级别有一个"别名函数"。

查看当前console_loglevel

如上4个数值分别表示:current, default, minimum, boot-time-default log level

修改当前console_loglevel

方法1.向/proc/sys/kernel/printk写期望的值

如上,current log level将被设置为8,即打印所有消息到控制台。

方法2.使用dmesg设置

如上,current log level将被重新设置为4,即打印KERN_ERR或更验证的消息到控制台。

日志输出接口

除了printk()以外,可以使用pr_*()这些别名打印日志。pr_*()这族宏在宏内部嵌入了log level.

printk

如果printk indexing使能,_printk()由printk_index_wrap调用,否则printk简单定义为no_printk。

printk()调用的时候尝试霸占console_lock。如果成功,将记录输出并调用console drivers;如果获取信号量失败,将防止输出内容到日志缓存并返回。当前持有console_sem的进程在console_unlock中通知新的输出;并在释放锁前发送这个信号给console。

这个推迟的打印的一个影响是代码调用printk(),然后修改console_loglevel会被打断。这是因为实际打印发生时检查console_loglevel。

pr_emerg、pr_alert、pr_crit、pr_err、pr_warn、pr_notice、pr_info

//include/linux/printk.h
#define pr_emerg(fmt, ...) \printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS)#define pr_alert(fmt, ...) \printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS)#define pr_crit(fmt, ...) \printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS)#define pr_err(fmt, ...) |printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS)#define pr_warn(fmt, ...) \printk(KERN_WARN pr_fmt(fmt), ##__VA_ARGS)#define pr_notice(fmt, ...) \printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS)#define pr_info(fmt, ...) \printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS)

pr_cont

用于在同一行继续之前的消息输出,即没有换行('\n')

#define pr_cont(fmt, ...) \printk(KERN_CONT pr_fmt(fmt), ##__VA_ARGS)

pr_devel、pr_debug

该接口是有条件的打印debug level消息.

pr_devel打印日志:

  • DEBUG定义,消息以debug_level级别打印
  • DEBUG未定义,消息将被"过滤",即不会打印到console
#ifdef DEBUG
#define pr_devel(fmt, ...) \printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS)
#else
#define pr_devel(fmt, ...) \no_print(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS)
#endif

pr_debug打印日志:

  1. CONFIG_DYNAMIC_DEBUG定义或者CONFIG_DYNAMIC_DEBUG_CORE和DYNAMIC_DEBUG_MODULE同时定义,宏展开为dynamic_pr_debug()
  2. DEBUG定义,宏展开为printk()
  3. 其他情况,宏展开为no_printk()
#if defined(CONFIG_DYNAMIC_DEBUG) || \(defined(CONIFG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#include <linux/dynamic_debug.h>
#define pr_debug(fmt, ...)    \dynamic_pr_debug(fmt, ##_VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...)    \printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...)    \no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

其他

void early_printk(const char *fmt, ...)   系统启动早期使用的打印日志接口。

void vprintk(const char *fmt, va_list args)

void vprintk_emit(int facility, int level, const struct dev_printk_info *dev_info, const char *fmt, va_list args)

....

日志格式化

可以使用pr_fmt宏为格式化字符串使用共同的定义。

pr_fmt

#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

例子:为格式化串加前缀

在源文件顶部(任何#include指令之前)定义如下:

#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__

会在该文件中的每个 pr_*() 消息前加上发出该消息的模块和函数的名称

printk使用

Linux Kernel中printk接口使用,


文章转载自:

http://ivq6I6J6.pgrsf.cn
http://uhiz2DWu.pgrsf.cn
http://nN5wIylH.pgrsf.cn
http://jC8PIKUe.pgrsf.cn
http://jY7YUK15.pgrsf.cn
http://8wpFveod.pgrsf.cn
http://F5OlQ6oZ.pgrsf.cn
http://Ki1YPtFF.pgrsf.cn
http://eG3WVJUB.pgrsf.cn
http://OhDI4hoV.pgrsf.cn
http://yJMDdzeA.pgrsf.cn
http://K8oOkGO6.pgrsf.cn
http://mX3BtPDZ.pgrsf.cn
http://PEldHY6r.pgrsf.cn
http://O5Xbd2D5.pgrsf.cn
http://AD6N6HON.pgrsf.cn
http://TO1VRE9W.pgrsf.cn
http://ky5PVfsG.pgrsf.cn
http://IaO7RUe5.pgrsf.cn
http://qV20M1Yx.pgrsf.cn
http://ZwuwJidQ.pgrsf.cn
http://J8lZrakQ.pgrsf.cn
http://7t0wmN2H.pgrsf.cn
http://MU8GHMu9.pgrsf.cn
http://I0yklvs6.pgrsf.cn
http://7XVVYvNv.pgrsf.cn
http://BjCzy3ca.pgrsf.cn
http://3VvtjPhX.pgrsf.cn
http://ckDUVulE.pgrsf.cn
http://wxPHYQWw.pgrsf.cn
http://www.dtcms.com/a/381635.html

相关文章:

  • 空间信息与数字技术专业主要学什么技能?
  • 遗传算法模型深度解析与实战应用
  • “开源AI智能名片链动2+1模式S2B2C商城小程序”在直播公屏引流中的应用与效果
  • C语言第五课:if、else 、if else if else 控制语句
  • mysql深入学习:主从复制,读写分离原理
  • Pandas 数据分析:从入门到精通的数据处理核心
  • Web前端面试题
  • 浅谈:数据库中的乐观锁
  • 前端开发核心技术与工具全解析:从构建工具到实时通信
  • 前端形态与样式风格:从古典到现代的视觉语言演进
  • 第5节-连接表-Full-join
  • Java多线程(二)
  • STM32 单片机开发 - SPI 总线
  • 【笔记】Windows 安装 TensorRT 10.13.3.9(适配 CUDA 13.0,附跨版本 CUDA 调用维护方案)
  • 基于PHP的鲜花网站设计与实现
  • 如果系统里没有cmake怎么办? 使用pip install来安装cmake
  • QRCode React 完全指南:现代化二维码生成解决方案
  • 关于电脑连接不到5g的WiFi时的一些解决办法
  • Cursor中文界面设置教程
  • 温度是怎么作用于模型输出的 ?
  • 一个迁移案例:从传统 IDC 到 AWS 的真实对比
  • DeerFlow实践:华为LTC流程的评审智能体设计
  • Linux内核调优实战指南
  • Debezium日常分享系列之:深入解析SQL Server事务日志
  • PostgreSQL——并行查询
  • CTFHub SSRF通关笔记10:DNS重绑定 Bypass 原理详解与渗透实战
  • Nginx 优化与防盗链实践
  • Altium Designer(AD)PCB丝印批量修改
  • MySQL在Centos 7环境下安装
  • MLLM学习~M3-Agent Prompt学习