カーネルコードの表示やエラー追跡に 使えるテクニックを紹介する
Download
Report
Transcript カーネルコードの表示やエラー追跡に 使えるテクニックを紹介する
Linux Device Driver 輪講
2. デバックのテクニック
ACE suzuk
table of contents
1.
2.
3.
4.
5.
6.
カーネルにおけるデバッグのサポート
表示させてのデバッグ
問い合わせによるデバッグ
観察によるデバッグ
システムフォルトのデバッグ
デバッガと関連ツール
はじめに
カーネルプログラミング、それ自体がユニーク
なデバッグ方法への挑戦です
カーネルコードをデバッガ上で簡単に実行できな
い
コードをトレースするのも大変
この章では、カーネルコードの表示やエラー追跡に
使えるテクニックを紹介する
1.カーネルにおけるデバッグのサポート
カーネルのデバッグ機能を有効にする
通常の製品カーネルでは、デバッグ機能が有効に
なっていない
カーネル設定ツールの「kernel hackig」メ
ニュー以下を探せ!
CONFIG_DEBUG_KERNEL
カーネルデバッグのフラグ、オンにする
CONFIG_DEBUG_INFO
カーネルに完全なデバッグ情報を含んでビルドする。
gdbを使う場合に必用
CONFIG_DEBUG_STACK_USAGE
カーネルのスタックオーバーフローをチェック
2.表示させてのデバッグ
printkによるメッセージ表示
デバッグのテクニックとして最も良く使われる方法
大きな特徴はログレベルを指定できること
ログレベルマクロは文字列に展開される
KERN_DEBUG
デバッグ用のメッセイー時
デバッグメッセージ出力デーモン
klogd, syslogd (通常/var/log/messagesに追
加)
/proc/sys/kernel/printkにログレベルの設定
現在のログレベルなど
コンソールメッセージのリダイレクション
「別の」仮想ターミナルでメッセージを受け取る
には、ioctl(TIOCLINUX)を実行
ioctlの特別なコマンド
ターミナルIOコマンドの略
仮想ターミナル0番でメッセージを受け取る例
char bytes[2] = {11, 0}; /* 11はコマンド番号 */
ioctl(STDIN_FILENO, TIOCLINUX, bytes);
メッセージを記録する方法
printk関数は__LOG_BUF_LENバイトの環
状バッファにメッセージを出力
カーネルメッセージを待ち構えている全てのプ
ロセスが目を覚ます
syslogシステムコールの中でスリープ or
/proc/kmsgを読んでいる(klogd)プロセス
dmesgコマンドはバッファの内容全体を出力
klogdがカーネルメッセージを回収して
syslogdに送る
klogdに–fオプションを渡しファイルに書き出せる
続いてsyslogdが/syslog.confを見てメッ
セージをどのように処理するかを決定する
メッセージを記録する方法 動作イメージ
printk
Write
head
1
2
ウ
Read
klogd
3
send mesg
z
z
ホ
syslogd
tail
z
メッセージのオン、オフを切り替える
デバッグメッセージのオン、オフを切り替えるこ
とができる
全てのデバッグメッセージ
個別のデバッグメッセージ
Cプリプロセッサを使い制
DEBUG = y
ifreq($(DEBUG), y)
DEBUGFLAGS = -O –g –DSCULL_DEBUG
else
DEBUGFLAGS = -O2
endif
CFLAGS += $(DEBFLAGS)
速度の制限
デバイスの不調など繰り返すメッセージ出力
関数
int printk_ratelimit(void);
いくつ出力されたかを管理する
/proc/sys/kernel/printk_ratelimit_burstで調
整可能
// how to use
if(printk_ratelimit()){
printk(KERN_NOTICE “printer ”
}
デバイス番号の表示
対象のハードウェアのデバイス番号を表示
int print_dev_t(char *buffer, dev_t dev);
char *format_dev_t(char *buffer, dev_t
dev);
問い合わせによるデバッグ
データをprintkで垂れ流すよりも、ユーザが
必要に応じて問い合わせる方が良い
問い合わせる方法たち
/procファイルシステム
ドライバにioctlを使う
属性をsysfsでエクスポートする方法(14章で)
/procファイルシステムを使う
/procファイルシステムはカーネルが情報を外
部にエクスポートするために使う
/proc/modules:現在ロードされたモジュール
注意!:新しいコードではsysfsを使うことをお勧
めする
/procにファイルを実装する 1/3
読み出し専用/procファイルの作成
<linux/proc_fs.h>をinclude
データ提供関数をドライバに実装
インタフェース
int (*read_proc)(char *page, char **start,
off_t offset, int count, int *eof, void *data)
page: データ書き込み先バッファ(1PAGE_SIZE)
start: どこから書き込んだデータが始まるのか
/procにファイルを実装する 2/3
/procファイルの作成 (scullの例)
create_proc_reawd_entry(“sculmem”, 0, NULL,
scull_read_procmem, NULL);
remove_proc_entry(“scullmem”, NULL /*親dir*/);
/procファイルシステムの問題点
参照回数をカウントしていない
プロセスが参照中に削除されることがある
モジュールがアンロードされていない間に/procエ
ントリの削除に失敗するとカーネルがクラッシュ
/procエントリは所有者が関連付けられていない、
重複名で登録される可能性がある
seq_fileインタフェース
大きなカーネル仮想ファイルの実装インタ
フェース
seq_openを使い、/procをseq_fileインタフェー
スに関連付ける
単純なiteratorオブジェクトを作成が必要
<linux/seq_file.h>をinclude
次の4つのiteratorメソッドを実装
start, next, stop, show
/procファイルを操作した際に、カーネルから呼ばれ
る
void *next(struct seq_file *sfile, void *v, loff_t *pos);
ioctlメソッドを使う
デバック用のioctlを実装しておくことができる
ドライバの構造体をユーザ空間にコピーできる
/proc読み出しよりも実行が速い
4.観察によるデバッグ
問題が深刻出ない場合、ユーザ空間のアプリ
を観察することで対処できる
デバッガによる順次実行
printf文による出力
straceの下でのプログラム実行
Straceとは
ユーザ空間プログラムが発行したシステムコール
をすべて表示
ドライバがシステムコールに応じて正しく実行され
ているかを確認するために有用
perror()以上の情報を得られる
5.システムフォルトのデバッグ
できるだけ多くの情報を集めることが重要
カーネルより吐き出されたメッセージ
CPUダンプも役立つ
システムフォルトやOopsでシステム全体が落
ちることはない
プロセスコンテキストに割り当てられたメモリが失
われる以外は大丈夫
最悪リブートすれば良い
Oopsメッセージ
CPUが特権モードの時にページフォルトが起
こったときにOopsメッセージを出力
大抵はポインタの取り扱いによるバグ
Oopsへの対処方法
CPUダンプのEIPを参照する
どこで問題が発生したかを知る
コールスタックから問題箇所に行き着いた経緯を
知る
システムのハングアップ
事前予防による対策
要所要所にschedule呼び出しを挿入
他のプロセスがCPU時間を奪えるようになる
ドライバのバグによるカーネル空間で無限ループから
復帰できる
事後のデバッグ
コンソールにメッセージ出力
どこにscheduleを挟めば良いかわからない時
偽のハングアップを見破るには時計やシステム不
可メータを表示するだけで有効
キーボードのロックなどにおいてはMagic
SysRqKeyが有効
6.デバッガと関連ツール
デバッガを使ったデバッグはとても時間がか
かるためできる限り避けるべき
1.
2.
3.
4.
5.
6.
gdbを使う
kdbカーネルデバッガ
kdbdパッチ
ユーザモードLinux
Linux Trace Toolkit
Dynamic Probes
gdbを使う
実行コマンド
gdb /usr/src/linux/vmlinux /proc/kcore
制限
カーネルデータを変更できない
ブレークポイント、ウォッチポイントの設定できない
シングルステップ実行できない
モジュールをテストするのは難しい
必要とされる能力
gdbコマンドの使い手
アセンブリコードを理解できる
ソースと最適化アセンブリを対応付けられる
kdbカーネルデバッガ
内蔵のカーネルデバッガ(非公式)
ブレークポイントの設置
スタックトレース
kgdbパッチ
リモートデバッグを可能にするパッチ
テストマシンと、開発用マシンを分けることができ
る
2.6で正式にマージされる予定
ユーザモードLinux
ユーザプロセスとしてカーネルを実行
Linuxシステムコールインタフェースを実装した仮
想マシン上で実行される
カーネルのコピーをユーザモードで走らせる
/arch/um以下を使い、Linuxカーネルの独立し
たポートとして構築
異なるハードウェアやソフトウェアを試すことができる
ハードウェアにアクセスできない制限がある
Linux Trace Toolkit (LTT)
カーネルパッチのひとつ
カーネル中のイベントトレース用のユーティリティ
特定の期間に発生したイベント全体像を取得できる
デバッグや性能上の問題に利用できる
Dynamic Probes
ユーザ空間とカーネル空間の任意のポイント
にプローブを設置可能
プローブの機能
ユーザ空間に情報を報告
レジスタを変更す
カーネルの再構築やリブートを行う必要がない