Linux Kernel: prink(print kernel)によるメッセージ出力

printk()とは

printk(print kernel)は、ユーザ空間のprintf( print formatted )に相当します。注意すべき点として、printf()と以下の点が異なります。本記事では、この差異を説明します。

printf()との差異
  • フォーマット
  • ログレベルの存在
  • printk()のラッパーマクロの存在
  • ログの出力先がメッセージ用リングバッファ
  • メッセージ表示に使用するコマンド(dmesg等)の存在

         

printk()フォーマット

pritnk()フォーマットは、printfとほぼ同様です。差異は、ログレベル(0〜7, d, c)が指定できる点、実数型(double/float)をサポートしない点です。ログレベルは後ほど解説します。

文字列の書式は、「printf(3)を参考にする事(“$ man 3 printf”)」とソースコード中に記載されている。下表に、代表的な指定文字を示す。型に応じて、どの変換指定文字を使用すべきか迷った場合は、公式ドキュメントに逆引きが存在します。

変換指定文字意味
%c1文字として出力
%d10進数で出力
%x16進数で出力
%o8進数で出力
%f使用不可。浮動小数点(実数)をKernelはサポートしない
%d使用不可。浮動小数点(実数)をKernelはサポートしない
%s文字列として出力
%pポインタ情報を出力(ポインタ関連は変換指定文字が多数存在

なお、ログレベルと書式文字列の間には、”,”がありません。

KERN_WARNINGは、defineマクロで定義された”4″を意味します。C言語では自動的にログレベルと書式文字列(“Test〜”の部分)は、 文字列として結合されます。ログレベルを指定しなかった場合は、自動的にデフォルト値(KERN_WARNING)となります。

        

ログレベル一覧

文字列

defineマクロ

意味・用途
0KERN_EMERG システム停止前の緊急メッセージ
1KERN_ALERT 早急な対応が必要なエラー
2KERN_CRIT HWもしくはSWの致命的なエラー
3KERN_ERR ドライバ共通のエラー
4KERN_WARNING 警告(エラーとなる可能性がある)
5KERN_NOTICE 注意(エラーではない)
6KERN_INFO 情報通知
7KERN_DEBUG デバッグメッセージ専用
dKERN_DEFAULTデフォルトのログレベル
cKERN_CONTログの継続(タイムスタンプの更新を回避。ブート中専用)

            

printk()のラッパーマクロ

Kernel開発者は、printk()を高頻度で使用します。利便性を高めるために、printkに関するラッパーマクロが存在します。マクロは、”<Linux>/include/linux/printk.h“に定義されています。

良く使用するマクロは、ログレベルを省略できるマクロです。マクロは、以下のように定義されています。全てのログレベルに対して、マクロが用意されています(下表)。

文字列

ログレベル

ラッパーマクロ
0KERN_EMERGpr_emerg
1KERN_ALERTpr_alert
2KERN_CRITpr_crit
3KERN_ERRpr_err
4KERN_WARNINGpr_warningもしくはpr_warn
5KERN_NOTICEpr_notice
6KERN_INFOpr_info
7KERN_DEBUGpr_devel(#ifdefによって、”DEBUG”が0の場合はprintk()しない仕様)
cKERN_CONTpr_cont

上記の他にも、一度しかprintkを表示しないマクロや遅延表示するマクロが存在します。

          

printk()出力先のメッセージリングバッファ

printk()は、ログレベルに関わらず、Kernel内部ログバッファにメッセージを保存しています。このログバッファは循環式であり、バッファ上限値を超えた場合は古いメッセージをに上書きする形で新しいメッセージを保存します。なお、ログバッファにメッセージを書き込む前に、タイムスタンプが付与されます。

ログバッファのサイズ変更は、Linux Kernelビルド前設定(“make menuconfig”)で行います。変更対象は”CONFIG_LOG_BUF_SHIFT”で、Bitシフトでしか設定できません(下図)。

      

メッセージ表示に利用するdmesgコマンド

printk()で用いるログバッファは、dmesgコマンド で内容を表示できます。dmesgは、klogctl(システムコール)を使用して、ログバッファを読み取り、標準出力 に表示します(以下の例を参考)。出力行数が多いため、head/tail/less/grepなどのコマンドで、メッセージを取捨選択したほうが良いです。

ログ出力の程度を抑えるために、ユーザ設定のログレベルのメッセージだけを表示する仕組みがあります。その設定値は、”/proc/sys/kernel/printk”に記載されています。以下にprintkファイルに記載された設定値を示し、その設定値の意味を下表に示します。

設定

意味
console_loglevelログレベルが設定値より小さい場合のみ、コンソール出力可能。
default_message_level明示的にログレベルが設定されていないpritnk()メッセージのログレベル
minimum_console_loglevelconsole_loglevelに設定できる最小値
default_console_loglevelconsole_loglevelのデフォルト値

“/proc/sys/kernel/printk”は書き込み可能なファイルであるため、以下のように設定値を変更できます。ただし、管理者権限が必要です。

最後に余談ですが、Linuxは、dmesgとは別の仕組みでログが管理されています。システム内部では、klogd が周期的にログ内容を収集し、 /var/log/syslog に書き出しています。こちらに関しては、インフラ系の勉強時に記事を作成します。

        

参考

Linux Kernel公式ドキュメント

カーネル・ロギング: API と実装(IBM)

<Linux>kernel/printk/printk.c

         

あわせて読みたい

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です