1. 说明

根据内核文档整理而成,具体格式含义可查看内核文档,或点击如何获得正确的printk格式占位符(v6.6)如何获得正确的printk格式占位符(latest)查看。 linux-6.6相关内核文档路径如下:

Documentation/core-api/printk-formats.rst Documentation/translations/zh_CN/core-api/printk-formats.rst

2. 整数类型

内核的printk不支持%n,也不支持浮点格式(%e / %f / %g / %a)。在printk中使用任何不支持的占位符或长度限定符都会导致一个WARN并且终止vsnprintf()执行。注意,sizeof()返回类型为size_t。

type format(DEC) format(HEX)
char / short int / int %d %x
unsigned char / unsigned short int / unsigned int %u %x
long %ld %lx
unsigned long %lu %lx
long long %lld %llx
unsigned long long %llu %llx
s8 / s16 / s32 %d %x
u8 / u16 / u32 %u %x
s64 %lld %llx
u64 %llu %llx
size_t %zu %zx
ssize_t %zd %zx

如果type的大小依赖于配置选项 (例如sector_t, blkcnt_t) 或其大小依赖于架构(例如tcflag_t),则使用其可能的最大类型的格式占位符并显式强制转换为它。例如:

1printk("test: sector number/total blocks: %llu/%llu\n",
2      (unsigned long long)sector, (unsigned long long)blockcount);

3. 指针类型

一个原始指针值可以用%p打印,它将在打印前对地址进行哈希处理。内核也支持扩展占位符来打印不同类型的指针。

type format
普通指针 %p
错误指针 %pe
符号/函数指针 %ps / %pS[Rb] / %pB[b]
来自BPF / tracing追踪的探查指针 %p[ku]s
内核指针 %pK
未经修改的地址 %px
指针差异 %t[dx]
结构体资源(Resources) %p[rR]
物理地址类型 phys_addr_t %pa[p]
DMA地址类型dma_addr_t %pad
原始缓冲区为转义字符串 %*pE[achnops]
原始缓冲区为十六进制字符串 %*ph[CDN]
MAC/FDDI地址 %pM[RF] / % pm[R]
IPv4地址 %p[Ii]4[hnbl]
IPv6 地址 %pi6[c] / %pI6[c]
IPv4/IPv6地址(generic, with port, flowinfo, scope) %p[Ii]S[pfschnbl]
UUID/GUID地址 %pU[BbLl]
目录项(dentry)的名称 %p[Dd]{,2,3,4}
块设备(block_device)名称 %pg
va_format结构体 %pV
设备树节点 %pOF[fnpPcCF]
Fwnode handles %pfw[fP]
时间和日期 %pt[RT][dt][r][s]
clk结构体 %pC[n]
位图及其衍生物,如cpumask和nodemask %*pb[l]
标志位字段,如页标志、gfp_flags %pG[pgv]
网络设备特性 %pNF
V4L2和DRM FourCC代码(像素格式) %p4cc

一些扩展占位符会打印给定地址上的数据,而不是打印地址本身。在这种情况下,以下错误消息可能会被打印出来,而不是无法访问的消息

打印内容 描述
(null) data on plain NULL address
(efault) data on invalid address
(einval) invalid data on a valid address

4. 参考资料

  1. How to get printk format specifiers right(v6.6)
  2. 如何获得正确的printk格式占位符(v6.6)
  3. How to get printk format specifiers right(latest)
  4. 如何获得正确的printk格式占位符(latest)