6 出力フォーマット
DTraceには、フォーマット設定関数としてprintf
とprinta
が組み込まれており、Dプログラムから使用して出力のフォーマットを設定できます。Dコンパイラには、Cライブラリのprintf()
ルーチンにはない機能があるため、すでにprintf
をよく理解している場合でもこの章はお読みください。
この章では、trace
関数のフォーマット設定機能と、dtraceコマンドが集積体を表示するときに使用するデフォルトの出力フォーマットについても説明します。
printfアクション
printf
アクションには、trace
関数と同じようにデータをトレースする機能に、データや他のテキストを指定のフォーマットで出力する機能が組み合されています。printf
からDTraceに対する指示により、最初の引数の後ろにある各引数に関連付けられたデータがトレースされ、フォーマット文字列と呼ばれる最初のprintf
引数によって記述されるルールを使用して、結果がフォーマットされます。フォーマット文字列は、任意の数のフォーマット変換を含む規則的な文字列です。それぞれ%
文字で始まり、対応する引数のフォーマット設定方法を決定します。フォーマット文字列の最初の変換が2番目のprintf
引数に対応し、2番目の変換が3番目の引数に対応し、以降同様に続きます。変換と変換の間のテキストは一語一句そのまますべて出力されます。%
変換文字に続く文字が、対応する引数に対して使用されるフォーマットを表します。
Cライブラリのprintf()
関数とは異なり、DTraceのprintf
関数はDコンパイラによって認識される組込み関数です。Dコンパイラには、printf()
にはない、次を含む便利なサービスがDTrace printf
関数のためにいくつか用意されています。
-
Dコンパイラは、引数をフォーマット文字列の変換と比較します。引数の型とフォーマット変換に互換性がない場合、Dコンパイラはその問題を示すエラー・メッセージを表示します。
-
Dコンパイラは、
printf
のフォーマット変換でサイズ接頭辞を使用する必要がありません。Cのprintf
ルーチンは、%ld
(long
,の場合)、%lld
(long long
の場合)などの接頭辞を追加して、引数のサイズを指定する必要があります。Dコンパイラは、引数の型とサイズを認識するため、Dのprintf
文ではこのような接頭辞が不要です。 -
DTraceには、デバッグと監視に役立つフォーマット文字が追加されています。たとえば、
%a
フォーマット変換を使用すると、ポインタをシンボル名およびオフセットとして出力できます。
このような機能を実装するには、Dプログラムにおいて、DTraceのprintf
関数のフォーマット文字列を文字列定数として指定する必要があります。フォーマット文字列は、string
型の動的変数としては使用できません。
変換指定
フォーマット文字列の変換指定はそれぞれ%
で始まり、続けて次の情報を順番に指定します。
-
0個以上のフラグ(順番は任意)。「フラグ指定子」で説明するように、変換指定の意味を変更します。
-
最小フィールド幅(オプション)。変換後の値のバイト数がフィールド幅より小さい場合には、値が空白文字で埋められます。埋められるのは、デフォルトでは値の左側、左揃えフラグ(
-
)を指定している場合は右側です。フィールド幅は、アスタリスク(*
)でも指定でき、この場合のフィールド幅は、int
型の追加の引数の値に基づいて動的に設定されます。 -
次のことを示すオプションのprecision指定子。
-
d
、i
、o
、u
、x
およびX
の各変換に対して表示される最小桁数。フィールドは先頭のゼロで埋められます。これは、e
、E
およびf
の変換の基数文字の後に表示される桁数です。 -
g
およびG
の各変換の最大有効桁数。 -
または、
s
変換によって文字列から出力される最大バイト数。
精度の指定子は、ピリオド(
.
)の後にアスタリスク(*
)を続けるか、ピリオドの後に10進数文字列を続けて指定します。「幅と精度の指定子」を参照してください。 -
-
一連のサイズ接頭辞(オプション)。対応する引数のサイズを指定します。サイズ接頭辞は、Dでは必要ありませんが、Cの
printf()
関数との互換性のために用意されています。 -
変換指定子。引数に適用される変換のタイプを指定します。
Cのprintf()
関数は、%n$
,という形式(nは10進整数)の変換指定もサポートしています。DTraceのprintf
関数では、このタイプの変換指定はサポートされていません。
フラグ指定子
printf
の変換フラグを有効にするには、次の表に示すように、次の文字を1つ以上指定します。順序は問いません。
フラグ指定子 | 説明 |
---|---|
|
10進変換( |
|
変換の結果を、フィールド内で左揃えします。このフラグを指定しない場合、変換は右揃えされます。 |
|
符号付きの変換の結果を、常に符号( |
|
符号付き変換の先頭文字が符号でない場合や、符号付き変換の結果として文字がなくなった場合に、結果の前に空白文字を追加します。 |
|
選択した変換に代替書式が定義されている場合に、値をその代替書式に変換します。変換の代替フォーマットについては、該当する変換の項を参照してください。 |
|
|
幅と精度の指定子
最小フィールド幅を指定するには、任意のフラグ指定子の後に10進の文字列を続けます。この場合、フィールド幅は指定された桁数に設定されます。フィールド幅は、アスタリスク(*
)でも指定でき、この場合はint
型の追加の引数によってフィールド幅が決定されます。
たとえば、int
型の変数w
によって決定されるフィールド幅で整数x
を出力するには、次のようなD文を記述します。
printf("%*d", w, x);
フィールド幅は、?
文字でも指定できます。この場合は、オペレーティング・システム・カーネルのデータ・モデル内で、アドレスを(16進で)フォーマット設定するために必要な文字数に基づいて、フィールド幅が設定されます。幅は、カーネルが32ビットのデータ・モデルを使用している場合は8
に、64ビットのデータ・モデルを使用している場合には16
に設定されます。変換の精度は、ピリオド(.
),に10進数の文字列を続けて、またはピリオドにアスタリスク(*
)を続けて指定できます。アスタリスクを使用して精度を指定する場合、変換引数の前に追加したint
型の引数によって精度が指定されます。フィールド幅と精度の両方をアスタリスクで指定した場合、変換のprintf
の引数は、幅、精度、値の順で指定する必要があります。
サイズ接頭辞
ANSI Cプログラムでprintf()
を使用する場合は、変換引数のサイズと型を指定するために、サイズ接頭辞が必要です。Dコンパイラは、printf
コールでこの処理を自動的に実行するため、サイズ接頭辞は必要ありません。Cとの互換性のためにサイズ接頭辞は用意されていますが、Dプログラムでは明示的に非推奨となっています。派生型を使用するとき、コードが特定のデータ・モデルにバインドされるためです。
たとえば、データ・モデルに応じてtypedef
を異なる整数基本型に再定義する場合、両方のデータ・モデルで機能する単一のC変換を使用するには、基礎となる2つの型を明示的に認識したうえで、キャスト式を追加するか、複数のフォーマット文字列を定義する必要があります。Dコンパイラは、サイズ接頭辞を省略可能にして引数のサイズを自動的に決定することによって、この問題を自動的に解決します。
サイズ接頭辞は、フォーマット変換名の前に、またフラグ、幅、精度の指定子があればその後ろに指定し、次のようになります。
-
h
(オプション)。後に続くd
、i
、o
、u
、x
またはX
変換をshort
またはunsigned short
に適用することを指定します。 -
l
(オプション)。後に続くd
、i
、o
、u
、x
またはX
変換をlong
またはunsigned long
に適用することを指定します。 -
ll
(オプション)。後に続くd
、i
、o
、u
、x
またはX
変換をlong long
またはunsigned long long
に適用することを指定します。 -
L
(オプション)。後に続くe
、E
、f
、g
またはG
変換をlong double
に適用することを指定します。 -
l
(オプション)。後に続くc
変換をwint_t
引数に適用し、s
変換文字をwchar_t
引数のポインタに適用することを指定します。
変換フォーマット
変換文字 | 説明 |
---|---|
|
ポインタすなわち |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ポインタすなわち |
|
引数は、 |
|
引数は、 |
|
|
|
|
|
引数は、 |
|
|
|
|
|
|
printaアクション
printa
アクションを使用すると、Dプログラムで集積体の結果をフォーマット設定できます。この関数は、次のいずれかの形式を使用して呼び出します。
printa(@aggregation-name); printa(format-string, @aggregation-name);
関数の最初の形式を使用する場合、dtraceコマンドは常時、集積体データのスナップショットを取得し、集積体のデフォルト出力フォーマットと同じフォーマットで結果を出力します。「集積体」を参照してください。関数の2番目の形式を使用する場合、dtraceコマンドは常時、集積体データのスナップショットを取得し、次のルールに従ってフォーマット文字列に指定された変換に応じた出力を生成します。
-
フォーマット変換は、集積体を作成する際に使用したタプル・シグネチャと一致する必要があります。各タプル要素は1回ずつ使用できます。たとえば、次のようなD文でカウントを集積するとします。
@a["hello", 123] = count(); @a["goodbye", 456] = count();
次に、プローブ節にD文
printa(format-string , @a)
を追加すると、dtraceは集積体データのスナップショットを取得し、次の文を入力した場合と同じ結果を出力します。printf(format-string, "hello", 123); printf(format-string, "goodbye", 456);
次に、集積体に定義されている各タプルも同様に処理します。
-
printf
とは異なり、printa
で使用するフォーマット文字列に、すべてのタプル要素を含める必要はありません。長さ3のタプルと1つのフォーマット変換のみを使用できます。したがって、printa
出力では、任意のタプル・キーを省略できます。そのためには、集積体の宣言を変更して、省略するキーをタプルの末尾に移動し、そのキーに対応する変換指定子をprinta
フォーマット文字列から除外します。 -
フォーマット設定フラグ文字
@
を追加すると、出力に集積体の結果が含まれます。これは、printa
で使用した場合にのみ有効です。@
フラグは、任意の適切な形式変換指定子と組み合せることができます。また、1つのフォーマット文字列にこのフラグを複数回含めることができるため、出力内の任意の場所にタプルの結果を複数回表示できます。各集積関数とともに使用できる変換指定子のセットは、集積関数の結果の型によって決まります。次の表に集積体の結果の型を示します。
集積体 | 結果の種類 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
たとえば、avg
の結果にフォーマットを設定するには、%d
、%i
、%o
、%u
、%x
のいずれかのフォーマット変換を適用できます。quantize
、lquantize
およびllquantize
関数は、結果を単一の値としてではなくASCIIテーブルとしてフォーマット設定します。
次のDプログラムは、printa
を使用する例を示しています。profileプロバイダを使用してcallerの値をサンプリングし、結果を単純な表としてフォーマット設定しています。次のソース・コードを入力し、printa.d
という名前のファイルに保存します。
profile:::tick-1000 { @myagg[caller] = count(); } END { printa("%@8u %a\n", @myagg); }
dtraceコマンドを使用してこのプログラムを実行する場合は、数秒待ってから[Ctrl]キーを押しながら[C]キー
を押します。次のような出力が表示されます。
# dtrace -qs printa.d ^C 1 vmlinux`do_syscall_64+0x2f 1 vmlinux`___bpf_prog_run+0x528 1 vmlinux`page_frag_free+0x3e 1 vmlinux`__legitimize_mnt 1 vmlinux`seq_printf+0x1b 1 vmlinux`selinux_sb_show_options+0x39 1 vmlinux`strchr+0x1f 1 ip6_tables`ip6t_do_table+0xbb 2 vmlinux`__raw_callee_save___pv_queued_spin_unlock+0x10 14 libata`__dta_ata_sff_pio_task_1036+0x9e 12975 vmlinux`native_safe_halt+0x6