カーネルコードの表示やエラー追跡に 使えるテクニックを紹介する

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
 ユーザ空間とカーネル空間の任意のポイント
にプローブを設置可能
 プローブの機能
 ユーザ空間に情報を報告
 レジスタを変更す
 カーネルの再構築やリブートを行う必要がない