Solaris 动态跟踪指南

printf()

printf() 函数将跟踪数据的功能(就像先前使用的 trace() 函数一样)与以描述的特定格式输出数据和其他文本的功能组合在一起。printf() 函数会指示 DTrace 跟踪与第一个参数之后的每个参数关联的数据,然后使用第一个 printf() 参数说明的规则(称为格式字符串)来格式化结果。

格式字符串是包含任意数量的格式转换的规则字符串,其中的每个转换都以 % 字符开头,该字符说明如何设置对应的参数格式。格式字符串中的第一个转换对应于第二个 printf() 参数,第二个转换对应于第三个参数,依此类推。转换之间的所有文本将逐字列显。% 转换字符之后的字符说明要用于对应参数的格式。

printf(3C) 不同,DTrace printf() 是 D 编译器可识别的内置函数。D 编译器为 DTrace printf() 提供了几项在 C 库 printf() 中未提供的有用服务:

要实现这些功能,必须在 D 程序中将 DTrace printf() 函数中的格式字符串指定为字符串常量。格式字符串不能是 string 类型的动态变量。

转换规范

格式字符串中的每种转换规范都由 % 字符引入,在该字符后按顺序显示以下信息:

printf(3C) 函数还支持 % n$ 形式的转换规范,其中 n 是十进制整数;DTrace printf() 不支持此类型的转换规范。

标志说明符

可通过指定下列一个或多个字符(可以按任何顺序显示)来启用 printf() 转换标志:

'

十进制转换结果的整数部分(%i%d%u%f%g%G)的格式是通过使用非货币分组字符的千位分组字符设置的。某些语言环境(包括 POSIX C 语言环境)未提供用于此标志的非货币分组字符。

-

转换结果将在字段中左对齐。如果未指定此标志,则转换将右对齐。

+

带符号的转换结果始终以符号(+-)开头。如果未指定此标志,则仅当转换负值时,转换才以符号开头。

空格

如果带符号的转换的第一个字符不是符号或者未产生任何字符,则会在结果前放置空格。如果同时出现空格+ 标志,则将忽略空格标志。

#

如果为所选转换定义了替换形式,则会将该值转换为替换形式。转换的替换格式将与对应转换一起说明。

0

对于 diouxXeEfgG 转换,前导零(跟在任何符号或基数表示之后)用于填充字段宽度。不会执行任何空格填充。如果同时出现 0- 标志,则将忽略 0 标志。对于 diouxX 转换,如果指定了精度,则将忽略 0 标志。如果同时出现 0' 标志,则会在进行零填充之前插入分组字符。

宽度和精度说明符

可将最小字段宽度指定为任意标志说明符后跟十进制数字字符串,在此情况下,字段宽度将设置为指定的列数。字段宽度还可以指定为星号 (*),在此情况下,将访问 int 类型的另一参数来确定字段宽度。例如,要在字段中列显整数 x(由 int 变量 w 的值确定),应编写如下 D 语句:

printf("%*d", w, x);

字段宽度也可使用 ? 字符来指定,以指定应根据设置地址格式(该地址在操作系统内核的数据模型中使用十六进制)所需的字符数来设置字段宽度。如果内核使用 32 位数据模型,则宽度设置为 8,如果内核使用 64 位数据模型,则宽度设置为 16。

转换的精度可指定为跟在句点 (.) 之后的十进制数字字符串,或者跟在句点之后的星号 (*)。如果使用星号来指定精度,则会访问转换参数之前的类型为 int 的另一参数来确定精度。如果宽度和精度都指定为星号,则对应转换的 printf() 参数的顺序应按以下顺序显示:宽度、精度、值。

大小前缀

在使用 printf(3C) 指示转换参数的大小和类型的 ANSI-C 程序中,需要使用大小前缀。因为 D 编译器会自动对 printf() 调用执行此处理,所以不需要大小前缀。尽管提供大小前缀是为了与 C 兼容,但因为在使用派生类型时它们会将代码绑定到特定数据模型,所以明确建议不要在 D 程序中使用它们。例如,如果根据数据模型将 typedef 重新定义为其他整数基本类型,则在未明确知道两种基础类型并且包括强制转换表达式(或定义多个格式字符串)的情况下,不能使用单个 C 转换来同时处理两种数据模型。D 编译器通过允许省略大小前缀并自动确定参数大小来自动解决此问题。

大小前缀只能放在格式转换名称之前和所有标志、宽度以及精度说明符之后。大小前缀如下所示:

转换格式

每个转换字符序列都将导致提取零个或多个参数。如果没有为格式字符串提供足够的参数,或者格式字符串已用完但仍有参数剩余,则 D 编译器将发出相应的错误消息。如果指定了未定义的转换格式,则 D 编译器将发出相应的错误消息。转换字符序列为:

a

指针或 uintptr_t 参数将列显为如下形式的内核符号名:module `symbol-name 加上十六进制字节偏移(可选)。如果该值不在已知内核符号定义的范围内,则该值将列显为十六进制整数。

c

charshortint 参数将列显为 ASCII 字符。

C

如果字符为可列显的 ASCII 字符,则 charshortint 参数将列显为 ASCII 字符。如果该字符不是可列显字符,则将使用表 2–5 中说明的对应转义序列将其列显。

d

charshortintlonglong long 参数将列显为十进制(以 10 为基数)整数。如果参数类型为 signed,则将列显为带符号的值。如果参数类型为 unsigned,则将列显为无符号值。此转换与 i 具有相同的含义。

e, E

floatdoublelong double 参数将转换为 [-] d.ddddd 样式,其中基数字符前有一位,基数字符后的位数等于精度。如果参数不为零,则基数字符也不为零。如果未指定精度,则缺省精度值为 6。如果精度为 0 并且未指定 # 标志,则不会显示任何基数字符。E 转换格式将生成一个数字,该数字将使用 E 而不是 e 来引入指数。指数总是至少包含两位数。该值将向上舍入为相应的位数。

f

floatdoublelong double 参数将转换为 [-] ddd.ddd 样式,其中基数字符之后的位数等于指定的精度。如果未指定精度,则缺省精度值为 6。如果精度为 0 并且未指定 # 标志,则不会显示任何基数字符。如果显示基数字符,则它之前至少会显示一位数字。该值将向上舍入为相应的位数。

g, G

floatdoublelong double 参数将列显为 fe 样式(如果使用 G 转换字符则为 E 样式),并且使用指定有效数字位数的精度。如果显式精度为 0,则会将其视为 1。使用的样式取决于转换的值:仅当转换生成的指数小于 -4 或大于等于精度时, 才会使用 e(或 E)样式。结果的小数部分中的结尾零将删除。仅当基数字符后跟数字时,才会显示基数字符。如果指定了 # 标志,则不会从结果中删除结尾零。

i

charshortintlonglong long 参数将列显为十进制(以 10 为基数)整数。如果参数类型为 signed,则将列显为带符号的值。如果参数类型为 unsigned,则将列显为无符号值。此转换与 d 具有相同的含义。

o

charshortintlonglong long 参数将列显为无符号的八进制(以 8 为基数)整数。signed 类型或 unsigned 类型的参数可用于与此转换。如果指定了 # 标志,则在需要将结果的第一位强制为零时,结果的精度将增加。

p

指针或 uintptr_t 参数将列显为十六进制(以 16 为基数)整数。D 接受任何类型的指针参数。如果指定了 # 标志,则将在非零结果的开头加上 0x

s

参数必须为 char 数组或 string。将一直读取数组或 string 中的字节,直到达到终止空字符或数据的结尾,并将其解释和列显为 ASCII 字符。如果未指定精度,则会将其视为无穷的,所以将列显所有字符,直到达到第一个空字符。如果指定了精度,则仅会列显在对应屏幕列数中显示的那一部分字符数组。如果要格式化 char * 类型的参数,则应将该参数强制转换为 string,或者使用 D stringof 运算符为前缀,以指示 DTrace 应跟踪的字符串字节数并设置这些字节的格式。

S

参数必须为 char 数组或 string。参数将按类似 %s 转换的方式进行处理,但不可列显的所有 ASCII 字符都将替换为表 2–5 中说明的对应转义序列。

u

charshortintlonglong long 参数将列显为无符号十进制(以 10 为基数)整数。signed 类型或 unsigned 类型的参数可用于此转换,并且结果都将格式化为 unsigned

wc

int 参数将转换为宽字符 (wchar_t) 并且将列显生成的宽字符。

ws

参数必须为 wchar_t 数组。会一直读取数组中的字节,直到达到终止空字符或数据结尾,并将其解释和列显为宽字符。如果未指定精度,则会将其视为是无穷的,所以将列显所有宽字符,直到达到第一个空字符。如果指定了精度,则仅会列显在对应屏幕列数中显示的那一部分宽字符数组。

x, X

charshortintlonglong long 参数将列显为无符号十六进制(以 16 为基数)整数。signed 类型或 unsigned 类型的参数可用于与此转换。如果使用 x 形式的转换,则将使用字母数字 abcdef。如果使用 X 形式的转换,则将使用字母数字 ABCDEF。如果指定了 # 标志,则将在非零结果的开头加上 0x(对于 %x)或 0X(对于 %X)。

Y

uint64_t 参数将解释为自 1970 年 1 月 1 日 00:00 世界标准时间以来的纳秒数,并且按以下 cftime(3C) 形式列显:"%Y %a %b %e %T %Z"。自 1970 年 1 月 1 日 00:00 世界标准时间以来的当前纳秒数将通过 walltimestamp 变量提供。

%

列显文字 % 字符。不会转换任何参数。完整的转换规范必须为 %%