首页 > 其他分享 >How to get printk format specifiers right (如何正确使用printk格式说明符)(翻译 by chatgpt)

How to get printk format specifiers right (如何正确使用printk格式说明符)(翻译 by chatgpt)

时间:2023-12-07 22:55:42浏览次数:42  
标签:specifiers right 打印 地址 用于 名称 使用 printk 指针

原文:https://www.kernel.org/doc/html/latest/core-api/printk-formats.html#printk-specifiers

如何正确使用printk格式说明符

整数类型

  如果变量是Type类型,      则使用printk格式说明符:

    signed char             %d或%hhx
    unsigned char           %u或%x
    char                    %u或%x
    short int               %d或%hx
    unsigned short int      %u或%x
    int                     %d或%x
    unsigned int            %u或%x
    long                    %ld或%lx
    unsigned long           %lu或%lx
    long long               %lld或%llx
    unsigned long long      %llu或%llx
    size_t                  %zu或%zx
    ssize_t                 %zd或%zx
    s8                      %d或%hhx
    u8                      %u或%x
    s16                     %d或%hx
    u16                     %u或%x
    s32                     %d或%x
    u32                     %u或%x
    s64                     %lld或%llx
    u64                     %llu或%llx

如果<type>的大小与体系结构相关(例如,cycles_ttcflag_t),或者依赖于配置选项的大小(例如,blk_status_t),则使用其最大可能类型的格式说明符,并显式转换为该类型。

示例:

printk("test: latency: %llu cycles\n", (unsigned long long)time);

提醒:sizeof()返回类型size_t。

内核的printf不支持%n。浮点格式(%e,%f,%g,%a)也不被识别,原因是显而易见的。使用任何不支持的说明符或长度限定符都会导致WARN并从vsnprintf()中提前返回。

指针类型

原始指针值可以使用%p打印,它会在打印之前对地址进行哈希处理。内核还支持用于打印不同类型指针的扩展说明符。

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

(null)   在普通NULL地址上的数据
(efault) 在无效地址上的数据
(einval) 在有效地址上的无效数据

普通指针

%p      abcdef12或00000000abcdef12

打印没有指示符扩展(即未装饰的%p)的指针会进行哈希处理以防止泄露有关内核内存布局的信息。这还具有提供唯一标识符的附加好处。在64位机器上,前32位被清零。内核将打印(ptrval),直到收集足够的熵。

如果可能,请使用专门的修饰符,例如%pS%pB(下面描述),以避免提供后期解释的未哈希地址的需要。如果不可能,并且打印地址的目的是为了提供更多的调试信息,请使用%p,并在调试期间使用no_hash_pointers内核参数引导内核,这将打印所有未修改的%p地址。如果您确实始终希望使用未修改的地址,请参阅下面的%px

如果(仅当)将地址作为虚拟文件的内容打印,例如在procfssysfs中由用户空间进程读取(使用seq_printf(),而不是printk()),请使用下面描述的%pK修饰符,而不是%p%px

错误指针

%pe     -ENOSPC

用于打印错误指针(即IS_ERR()为true的指针)作为符号错误名称。对于没有已知符号名称的错误值,以十进制形式打印,而将非ERR_PTR作为%pe的参数传递的情况将被视为普通%p

符号/函数指针

%pS     versatile_init+0x0/0x110
%ps     versatile_init
%pSR    versatile_init+0x9/0x110
(带有__builtin_extract_return_addr()转换)
%pB     prev_fn_of_versatile_init+0x88/0x88

Ss说明符用于以符号格式打印指针。它们导致带有(S)或不带(s)偏移量的符号名称。如果禁用了KALLSYMS,则打印符号地址。

B说明符导致带有偏移量的符号名称,并且在打印堆栈回溯时应使用。该说明符考虑了编译器优化的影响,当使用尾调用并标记为noreturn GCC属性时,可能会发生优化。

如果指针在模块内,则在符号名称之后打印模块名称和可选的构建ID,并在说明符的末尾附加一个额外的b。

%pS     versatile_init+0x0/0x110 [module_name]
%pSb    versatile_init+0x0/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
%pSRb   versatile_init+0x9/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
(带有__builtin_extract_return_addr()转换)
%pBb    prev_fn_of_versatile_init+0x88/0x88 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]

来自BPF /跟踪的探测指针

%pks    内核字符串
%pus    用户字符串

ku说明符用于打印来自内核内存(k)或用户内存(u)的先前探测内存。随后的s说明符导致打印字符串。对于直接在常规vsnprintf()中使用,将忽略(k)和(u)注释,但是,例如,在BPF的bpf_trace_printk()之外使用时,它会读取它指向的内存而不会出错。

内核指针

%pK     01234567 或 0123456789abcdef

用于打印内核指针,这些指针应该对非特权用户隐藏。%pK 的行为取决于 kptr_restrict sysctl - 有关更多详细信息,请参阅 /proc/sys/kernel/ 的文档。

此修改器仅用于生成由用户空间读取的文件内容,例如 procfs 或 sysfs,而不适用于 dmesg。有关如何在 printk() 中管理哈希指针的讨论,请参阅上面关于 %p 的部分。

未修改的地址

%px     01234567 或 0123456789abcdef

用于打印指针,当您真正想打印地址时。在使用 %px 打印指针之前,请考虑您是否泄露了有关内核内存布局的敏感信息。 %px 在功能上等同于 %lx(或 %lu)。 %px 更受欢迎,因为它更容易被 grep。如果将来我们需要修改内核处理打印指针的方式,我们将更好地找到调用点。

在使用 %px 之前,请考虑在调试会话期间使用 %p 并启用 no_hash_pointers 内核参数是否足够(请参阅上面的 %p 描述)。%px 的一个有效场景可能是在 panic 发生之前立即打印信息,这样可以防止利用任何敏感信息,而且使用 %px 就无需使用 no_hash_pointers 重现 panic。

指针差异

%td     2560
%tx     a00

用于打印指针差异,使用 %t 修饰符来表示 ptrdiff_t

示例:

printk("test: difference between pointers: %td\n", ptr2 - ptr1);

结构资源

%pr     [mem 0x60000000-0x6fffffff flags 0x2200] 或
        [mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
%pR     [mem 0x60000000-0x6fffffff pref] 或
        [mem 0x0000000060000000-0x000000006fffffff pref]

用于打印结构资源。Rr 修饰符会导致打印带有(R)或不带(r)解码标志成员的资源。

通过引用传递。

物理地址类型 phys_addr_t

%pa[p]  0x01234567 或 0x0123456789abcdef

用于打印 phys_addr_t 类型(以及其派生类型,例如 resource_size_t),这取决于构建选项,而不受 CPU 数据路径宽度的影响。

通过引用传递。

DMA 地址类型 dma_addr_t

%pad    0x01234567 或 0x0123456789abcdef

用于打印 dma_addr_t 类型,这取决于构建选项,而不受 CPU 数据路径宽度的影响。

通过引用传递。

作为转义字符串的原始缓冲区

%*pE[achnops]

用于打印原始缓冲区作为转义字符串。对于以下缓冲区:

1b 62 20 5c 43 07 22 90 0d 5d

以下是一些示例,显示了如何进行转换(不包括周围的引号):

%*pE            "\eb \C\a"\220\r]"
%*pEhp          "\x1bb \C\x07"\x90\x0d]"
%*pEa           "\e\142\040\\103\a\042\220\r\135"

根据可选的标志组合应用转换规则(有关详细信息,请参阅 string_escape_mem() 内核文档):

  • a - ESCAPE_ANY
  • c - ESCAPE_SPECIAL
  • h - ESCAPE_HEX
  • n - ESCAPE_NULL
  • o - ESCAPE_OCTAL
  • p - ESCAPE_NP
  • s - ESCAPE_SPACE

默认情况下使用 ESCAPE_ANY_NP

对于许多情况来说,ESCAPE_ANY_NP 是明智的选择,特别是用于打印 SSID。

如果省略字段宽度,则只会转义 1 个字节。

作为十六进制字符串的原始缓冲区

%*ph    00 01 02  ...  3f
%*phC   00:01:02: ... :3f
%*phD   00-01-02- ... -3f
%*phN   000102 ... 3f

用于将小缓冲区(最多 64 个字节长)打印为带有特定分隔符的十六进制字符串。对于较大的缓冲区,请考虑使用 print_hex_dump()

MAC/FDDI 地址

%pM     00:01:02:03:04:05
%pMR    05:04:03:02:01:00
%pMF    00-01-02-03-04-05
%pm     000102030405
%pmR    050403020100

用于以十六进制表示打印 6 字节的 MAC/FDDI 地址。M 和 m 修饰符会导致打印带有(M)或不带(m)字节分隔符的地址。默认字节分隔符是冒号(:)。

对于 FDDI 地址,可以在 M 修饰符之后使用 F 修饰符,以使用破折号(-)分隔符代替默认分隔符。

对于蓝牙地址,应在 M 修饰符之后使用 R 修饰符,以使用适合蓝牙地址的反向字节顺序进行可视化解释,这些地址采用小端序。

通过引用传递。

IPv4地址

%pI4    1.2.3.4
%pi4    001.002.003.004
%p[Ii]4[hnbl]

用于打印IPv4点分十进制地址。I4和i4格式化符会打印带有(i4)或不带有(I4)前导零的地址。

额外的h、n、b和l格式化符分别用于指定主机、网络、大端或小端顺序的地址。如果没有提供格式化符,则使用默认的网络/大端顺序。

通过引用传递。

IPv6地址

%pI6    0001:0002:0003:0004:0005:0006:0007:0008
%pi6    00010002000300040005000600070008
%pI6c   1:2:3:4:5:6:7:8

用于打印IPv6网络顺序的16位十六进制地址。I6和i6格式化符会打印带有(I6)或不带有(i6)冒号分隔符的地址。始终使用前导零。

如果使用了额外的c格式化符,则可以与I格式化符一起使用,以打印压缩的IPv6地址,如https://tools.ietf.org/html/rfc5952所述。

通过引用传递。

IPv4/IPv6地址(通用,带有端口、流信息和范围)

%pIS    1.2.3.4         或 0001:0002:0003:0004:0005:0006:0007:0008
%piS    001.002.003.004 或 00010002000300040005000600070008
%pISc   1.2.3.4         或 1:2:3:4:5:6:7:8
%pISpc  1.2.3.4:12345   或 [1:2:3:4:5:6:7:8]:12345
%p[Ii]S[pfschnbl]

用于打印IP地址,无需区分是AF_INET还是AF_INET6类型。可以将指向有效struct sockaddr的指针通过ISiS传递给此格式化符。

额外的pfs格式化符用于指定端口(IPv4、IPv6)、流信息(IPv6)和范围(IPv6)。端口使用:前缀,流信息使用/,范围使用%,后跟实际值。

对于IPv6地址,如果提供了额外的c格式化符,则使用 https://tools.ietf.org/html/rfc5952 所述的压缩IPv6地址。如果使用了额外的p、f或s格式化符,则根据 https://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07 的建议,IPv6地址将用[]括起来。

对于IPv4地址,也可以使用额外的h、n、b和l格式化符,但在IPv6地址的情况下将被忽略。

通过引用传递。

进一步的示例:

%pISfc          1.2.3.4         或 [1:2:3:4:5:6:7:8]/123456789
%pISsc          1.2.3.4         或 [1:2:3:4:5:6:7:8]%1234567890
%pISpfc         1.2.3.4:12345   或 [1:2:3:4:5:6:7:8]:12345/123456789

UUID/GUID地址

%pUb    00010203-0405-0607-0809-0a0b0c0d0e0f
%pUB    00010203-0405-0607-0809-0A0B0C0D0E0F
%pUl    03020100-0504-0706-0809-0a0b0c0e0e0f
%pUL    03020100-0504-0706-0809-0A0B0C0E0E0F

用于打印16字节的UUID/GUID地址。额外的l、L、b和B格式化符用于指定小端顺序的小写(l)或大写(L)十六进制表示法,以及大端顺序的小写(b)或大写(B)十六进制表示法。

如果不使用额外的格式化符,则将打印默认的大端顺序和小写十六进制表示法。

通过引用传递。

dentry名称

%pd{,2,3,4}
%pD{,2,3,4}

用于打印dentry名称;如果与d_move()竞争,名称可能是旧名称和新名称的混合,但不会出错。%pd dentry是我们过去使用的%s dentry->d_name.name的更安全等效形式,%pd<n>打印最后n个组件。%pD对于struct file执行相同的操作。

通过引用传递。

block_device名称

%pg     sda、sda1或loop0p1

用于打印block_device指针的名称。

struct va_format

%pV

用于打印struct va_format结构。它们包含格式字符串和va_list,如下所示:

struct va_format {
const char *fmt;
va_list *va;
};

实现了“递归vsnprintf”。

在没有某种机制来验证格式字符串和va_list参数的正确性的情况下,请不要使用此功能。

通过引用传递。

设备树节点

%pOF[fnpPcCF]

用于打印设备树节点结构。默认行为等同于%pOFf。

  • f - 设备节点的完整名称
  • n - 设备节点的名称
  • p - 设备节点的phandle
  • P - 设备节点的路径规范(名称 + @单元)
  • F - 设备节点的标志
  • c - 主要兼容字符串
  • C - 完整兼容字符串

当使用多个参数时的分隔符是“:”

示例:

%pOF    /foo/bar@0                      - 节点的完整名称
%pOFf   /foo/bar@0                      - 与上述相同
%pOFfp  /foo/bar@0:10                   - 节点的完整名称 + phandle
%pOFfcF /foo/bar@0:foo,device:--P-      - 节点的完整名称 +
                                          主要兼容字符串 +
                                          节点标志
                                              D - 动态
                                              d - 分离
                                              P - 已填充
                                              B - 已填充总线

通过引用传递。

Fwnode句柄

%pfw[fP]

用于打印fwnode句柄的信息。默认情况下,打印包括路径在内的完整节点名称。修饰符在功能上与上述的%pOF相同。

  • f - 节点的完整名称,包括路径
  • P - 节点的名称,包括地址(如果有)

示例(ACPI):

%pfwf   [email protected]@0        - 完整节点名称
%pfwP   endpoint@0                              - 节点名称

示例(OF):

%pfwf   /ocp@68000000/i2c@48072000/camera@10/port/endpoint - 完整名称
%pfwP   endpoint                                - 节点名称

时间和日期

%pt[RT]                 YYYY-mm-ddTHH:MM:SS
%pt[RT]s                YYYY-mm-dd HH:MM:SS
%pt[RT]d                YYYY-mm-dd
%pt[RT]t                HH:MM:SS
%pt[RT][dt][r][s]

以人类可读的格式打印日期和时间,表示为:

R  结构体rtc_time
T  time64_t类型

默认情况下,年份增加了1900,月份增加了1。使用%pt[RT]r(原始)来禁止此行为。

%pt[RT]s(空格)将使用“ ”(空格)而不是“T”(大写T)作为ISO 8601分隔符。当省略日期或时间时,它不会产生任何效果。

通过引用传递。

struct clk

%pC     pll1
%pCn    pll1

用于打印struct clk结构。%pC%pCn打印时钟的名称(通用时钟框架)或唯一的32位ID(传统时钟框架)。

通过引用传递。

位图及其派生物,如cpumask和nodemask

%*pb    0779
%*pbl   0,3-6,8-10

用于打印位图及其派生物,如cpumasknodemask%*pb将位图输出为具有位数作为字段宽度的位图,%*pbl将位图输出为范围列表,字段宽度为位数。

字段宽度通过值传递,位图通过引用传递。辅助宏cpumask_pr_args()nodemask_pr_args()可用于简化打印cpumasknodemask

标志位字段,如页面标志、页面类型、gfp_flags

%pGp    0x17ffffc0002036(referenced|uptodate|lru|active|private|node=0|zone=2|lastcpupid=0x1fffff)
%pGt    0xffffff7f(buddy)
%pGg    GFP_USER|GFP_DMA32|GFP_NOWARN
%pGv    read|exec|mayread|maywrite|mayexec|denywrite

以符号常量的集合形式打印标志位字段,这些符号常量将构建值。标志的类型由第三个字符给出。当前支持的类型有:

  • p - [p]age标志,期望类型为(unsigned long *)
  • t - page [t]ype,期望类型为(unsigned int *)
  • v - [v]ma_flags,期望类型为(unsigned long *)
  • g - [g]fp_flags,期望类型为(gfp_t *)

标志名称和打印顺序取决于特定类型。

请注意,此格式不应直接用于跟踪点的TP_printk()部分。相反,使用<trace/events/mmflags.h>中的show_*_flags()函数。

通过引用传递。

网络设备功能

%pNF    0x000000000000c000

用于打印netdev_features_t。

通过引用传递。

V4L2和DRM FourCC代码(像素格式)

%p4cc

打印V4L2或DRM使用的FourCC代码,包括格式的字节顺序和其十六进制的数值。

通过引用传递。

示例:

%p4cc   BG12 little-endian (0x32314742)
%p4cc   Y10  little-endian (0x20303159)
%p4cc   NV12 big-endian (0xb231564e)

Rust

%pA

仅用于从Rust代码中格式化core::fmt::Arguments。请勿从C中使用它。

感谢

如果您添加其他%p扩展,请在可能的情况下扩展<lib/test_printf.c>中的一个或多个测试用例。

感谢您的合作和关注。

标签:specifiers,right,打印,地址,用于,名称,使用,printk,指针
From: https://www.cnblogs.com/pengdonglin137/p/17868516.html

相关文章

  • 《最新出炉》系列初窥篇-Python+Playwright自动化测试-35-处理web页面定位toast-上篇
    1.简介在使用appium写app自动化的时候介绍toast的相关元素的定位,在WebUI测试过程中,也经常遇到一些toast(出现之后一闪而过,不留下一点点痕迹),那么这个toast我们这边如何使用playwright进行定位测试呢?今天宏哥就分两篇介绍一下。2.什么是toast?Android中的Toast是一种简易的消......
  • SQL Server中left join、inner join和right join的区别?
    数据库是我们IT行家常的事情,相信大家都不陌生,计算机专业都开了数据库系统概论这门课程,我分享下在暑假找实习参加宣讲会过程做的笔试题中遇到关于leftjoin、innerjoin和rightjoin的区别的简述题,希望对需要的朋友有所帮助。看下面一个小例子,我懒的开软件,用Excel替代下,谅解谅解~st......
  • 33基于playwright编写网络抓包工具
     fromplaywright.sync_apiimportsync_playwrightr'''可以利用playwright框架抓浏览器网络请求包,抓响应包输出会有识别不了的字符编码报错(暂无解决,或者不用解决)。'''#回调函数获取请求url、请求头、请求体defon_request(request):print(f'RequestURL:{request......
  • python+playwright爬取招聘网站
    一、简介:以获取智联招聘网北京、上海、广州、深圳的“数据分析”相关岗位的招聘信息为例,以下是效果实现。二、流程及代码实现(一)playwright模块安装或者在cmd中输入命令pipinstallplaywright安装完成后还需要安装playwright的浏览器驱动在cmd中输入命令playwrightinstall,等待即可......
  • python+playwright 学习-43 Pyinstaller打包生成独立的可执行文件
    前言playwright与Pyinstaller结合使用来创建独立的可执行文件。本地化安装有同学提到说想打成一个exe的独立包,但是执行playwrightinstall会默认把chromium,firefox和webkit三个浏览器安装到系统目录。这样打包的时候就找不到启动的浏览器文件。于是就想到把浏览器文件下......
  • python用playwright自动化测试程序打包exe
    playwright自动化测试代码写好后,打包为exe运行在目标PC上可能出现错误。原因:1、运行的PC没有响应的浏览器。2、playwright没有打包到代码中。所以本例用AutoPytoExe为例来制作exe程序解决问题。1、安装: 2、安装完成之后,我们就可以输入:auto-py-to-exe,来启动auto-py-to-exe......
  • Playwright爬虫绕过Cloudflare人机验证
    1.问题描述有些网关接入了Cloudflare的人机验证组件,当使用Playwright等自动化工具爬取的时候,会被人机验证阻拦。阻断的效果如下:2.问题原因Selenium、Puppeteer、Playwright等自动化控制工具的实现都会遵循一个规范,就是使用这些工具的时候,获取navigator的webdriver属性时......
  • 《最新出炉》系列初窥篇-Python+Playwright自动化测试-32-JavaScript的调用执行-下篇
    1.简介 在实际工作中,我们需要对处理的元素进行高亮显示,或者有时候为了看清楚操作过程和步骤我们需要跟踪鼠标点击了哪些元素需要标记出来。虽然很少遇到,但是为了以后大家可以参考或者提供一种思路,今天宏哥就在这里把这种测试场景playwright是如何处理的讲解和分享一下。2.用法......
  • 《最新出炉》系列初窥篇-Python+Playwright自动化测试-31-JavaScript的调用执行-上篇
    1.简介在做web自动化时,有些情况playwright的api无法完成以及无法应对,需要通过或者借助第三方手段比如js来完成实现,比如:去改变某些元素对象的属性或者进行一些特殊的操作,本文讲解playwright怎样来调用JavaScript完成特殊操作。2.用法上一篇中就提到过,这里提取一下,语法如下:......
  • 2023年第 17期《Python接口自动化+Playwright 》课程,12月3号开学(课程全面升级!)!
    2023年第17期《Python接口自动化+Playwright》课程课程,12月3号开学(课程全面升级!)主讲老师:上海-悠悠上课方式:微信群视频在线教学,方便交流本期上课时间:2023年12月3号-2024年3月2号,晚上20:30-22:30报名费:报名费3000一人(周期3个月)联系微信/QQ:283340479课表如下直播课程主要......