2005 年度上期 オープンソースソフトウェア活用基盤整備事業 「OSS 性能・信頼性評価 / 障害解析ツール開発」 OS 層 ~障害解析の手順・ツール評価編~ 作成 OSS 技術開発・評価コンソーシアム 商標表記 ・ Alicia は、ユニアデックス株式会社の登録商標です。 ・ Asianux は、ミラクル・リナックス株式会社の日本における登録商標です。 ・ Intel、Itanium および Intel Xeon は、アメリカ合衆国およびその他の国におけるイ ンテルコーポレーションまたはその子会社の商標または登録商標です。 ・ Intel は、Intel Corporation の会社名です。 ・ Linux は、Linus Torvalds の米国およびその他の国における登録商標あるいは商標です。 ・ MIRACLE LINUX は、ミラクル・リナックス株式会社が使用許諾を受けている登録商 標です。 ・ Pentium は、Intel Corporation のアメリカ合衆国及びその他の国における登録商標で す。 ・ Red Hat は、米国およびその他の国で Red Hat, Inc. の登録商標若しくは商標です。 ・ Solaris は、米国 Sun Microsystems, Inc. の米国およびその他の国における商標または 登録商標です。 ・ SUSE は、米国 Novell, Inc.の一部門である SUSE LINUX AG.の登録商標です。 ・ Turbolinux は、ターボリナックス株式会社の商標または登録商標です。 ・ UNIX は、X/Open Company Limited が独占的にライセンスしている米国ならびに他 の国における登録商標です。 ・ Windows は、米国およびその他の国における米国 Microsoft Corp.の登録商標です。 ・ その他記載の会社名、製品名は、それぞれの会社の商号、商標もしくは登録商標です。 - i - 目次 1 障害解析の概要 ..........................................................................................................1-1 1.1 障害解析の一般的手順.........................................................................................1-3 1.2 準備 .....................................................................................................................1-4 1.3 障害情報収集および初期切り分け.......................................................................1-5 1.4 再現および障害解析 ............................................................................................1-6 1.5 使用可能なツールとその分類..............................................................................1-7 1.5.1 2 3 章で評価するツールについて..................................................................1-15 障害解析手法と考察 ...................................................................................................2-1 2.1 障害事例の最近の傾向.........................................................................................2-1 2.2 一般的な障害解析手法.........................................................................................2-2 2.2.1 エラーメッセージ関連 .................................................................................2-2 2.2.2 アプリケーション異常終了 ..........................................................................2-4 2.2.3 スローダウン................................................................................................2-6 2.2.4 フリーズ.......................................................................................................2-9 2.2.5 カーネルパニック....................................................................................... 2-11 2.2.6 ネットワーク障害.......................................................................................2-13 2.2.7 ディスク障害..............................................................................................2-15 2.3 エラーメッセージ関連.......................................................................................2-17 2.3.1 2.4 スレッド生成不可(manページにないエラー)が発生する障害の解析 ....2-17 アプリケーション異常終了 ...............................................................................2-24 2.4.1 高負荷時にアプリケーションが異常終了する障害の解析(コアダンプなし) 2-24 2.4.2 高負荷時にアプリケーションが異常終了する障害の解析(コアダンプあり) 2-30 2.4.3 高負荷時にアプリケーションがOut of Memoryで強制終了された障害の解析 (コアダンプなし) .................................................................................................2-32 2.5 スローダウン.....................................................................................................2-34 2.5.1 パフォーマンス監視ツールの障害解析 ......................................................2-34 2.5.2 システムコールトレーサがトレース対象プロセスを遅延させる障害の解析 2-73 2.5.3 2.6 フリーズ ............................................................................................................2-94 2.6.1 2.7 フリーズ障害の解析 ...................................................................................2-94 カーネルパニック............................................................................................2-103 2.7.1 2.8 性能障害.....................................................................................................2-90 カーネルパニック障害の解析...................................................................2-103 ネットワーク障害............................................................................................ 2-112 2.8.1 障害概要................................................................................................... 2-112 2.8.2 障害検知................................................................................................... 2-112 2.8.3 障害切り分け............................................................................................ 2-113 - ii - 2.8.4 2.9 3 障害回復手順............................................................................................ 2-115 ディスク障害................................................................................................... 2-119 2.9.1 H/W RAID 5/1 ......................................................................................... 2-119 2.9.2 S/W RAID5/1 ...........................................................................................2-123 2.9.3 LVM .........................................................................................................2-127 ツール評価..................................................................................................................3-1 3.1 パフォーマンス監視ツールの信頼性評価 ............................................................3-1 3.1.1 ツールの概要................................................................................................3-1 3.1.2 評価環境.......................................................................................................3-4 3.1.3 評価項目.......................................................................................................3-7 3.1.4 評価手順.......................................................................................................3-7 3.1.5 評価結果.......................................................................................................3-8 3.2 プロファイラの機能評価 ...................................................................................3-39 3.2.1 ツール概要 .................................................................................................3-39 3.2.2 評価環境.....................................................................................................3-39 3.2.3 評価項目.....................................................................................................3-40 3.2.4 評価手順.....................................................................................................3-53 3.2.5 評価結果.....................................................................................................3-55 3.2.6 readprofile .................................................................................................3-66 3.2.7 考察 ............................................................................................................3-68 3.3 システムコールトレーサの評価 ........................................................................3-69 3.3.1 システムコールトレーサの概要 .................................................................3-69 3.3.2 strace評価環境 ...........................................................................................3-69 3.3.3 strace機能評価 ...........................................................................................3-69 3.3.4 strace信頼性評価(前提条件) ..................................................................3-73 3.3.5 strace信頼性評価(CPU負荷時)..............................................................3-76 3.3.6 strace信頼性評価(I/O負荷時) ................................................................3-79 3.3.7 strace信頼性評価(メモリ負荷時)...........................................................3-83 3.4 ネットワーク情報収集ツールの評価 .................................................................3-87 3.4.1 ツールの使用方法.......................................................................................3-87 3.4.2 bonding環境での機能評価 .........................................................................3-95 3.4.3 bonding機能検証手順 ..............................................................................3-102 3.4.4 bonding機能検証結果と考察....................................................................3-102 3.5 ディスク情報収集ツールの評価 ......................................................................3-105 3.5.1 ツールの使用方法.....................................................................................3-105 3.5.2 H/W RAID 5/1 評価環境 ......................................................................... 3-117 3.5.3 S/W RAID 5/1 ディスク評価環境............................................................3-122 3.5.4 LVM機能評価環境....................................................................................3-124 3.6 ダンプツールの評価 ........................................................................................3-134 3.6.1 ダンプ採取ツール.....................................................................................3-134 - iii - 3.6.2 3.7 4 ダンプ解析ツール.....................................................................................3-158 OSS障害解析ツールの問題点と対策 ...............................................................3-179 付録 <crash/lcrash/mdbコマンド結果比較>.........................................................4-1 - iv - 1 障害解析の概要 最近 OSS がエンタープライズ向けシステムへ適用される事例が多数見られるようになっ てきており、Linux の安定度は増してきていると思われる。しかし障害が発生した場合、そ の障害の種別によっては解析が困難な場合があり、エンタープライズ向けシステムに要求 される迅速な障害対応が実現できないことがある。また、ユーザもこのような状況に、OSS のサポートに対して漠然とした不安を持っていると思われる。 このような状況を作り出している要因として、以下が挙げられると考えた。 (1) 障害解析ノウハウの蓄積が不足している 解析ノウハウについて公開されているものもあるが、各種障害事例について集約/網 羅されているものは、今回は見出すことができなかった (2) 障害解析ツールの使用方法や問題点などが整理されていない 解析ツールに関する総括的な情報、たとえばどのようなツールを使うことによって、 どのような情報が得られるのか、また、ツール自体の問題点や不足している機能はない か、等が整理されていない この問題点をふまえ、本評価報告書では下記の点を目的とした。 (1) 代表的な障害事象について、事象毎にそれぞれ代表的な障害解析手法を示す (2) 障害解析事例を通じて、具体的な障害解析ノウハウを公開する (本報告書で取り上げた障害解析事例の一覧については、表 1.1-1 を参照) (3) OSS の障害解析ツールに絞って、現在普及している解析ツールの分類、および問題点や 不足している機能等をまとめた上で公開する 本評価報告書は、マニュアルを参照し障害切り分けを行うレベルから、ソースコード解 析を行うレベルまでの幅広い障害解析者を対象としており、障害解析時の参考資料および、 障害解析者の教育資料として活用されることを想定している。 これまで OSS においては、この種の報告書は存在しなかったと思われる。この報告書で 各種ノウハウを明示化することによって、より多くのフィードバックが重ねられ、それに よって OSS が更に発展することを期待する。 - 1-1 - 表 1.1-1 # 事象分類 1 障害事例および使用した解析ツール一覧 障害事例の概要 使用した主なツール 備考 エラーメッセージ ある特定の処理(多数のスレッドを生成)を行うとアプ strace 2.3.1 関連 リケーションが必ずエラーを出力する。仕様書には特に strace 2.4.1、2.4.2 /var/log/messages 2.4.3 lkst,ps 2.5.1 制限等の記載はない 2 アプリケーション 通常は何の問題もなく動くアプリケーションが、負荷が 異常終了 高くなるとセグメンテーションフォールトとなる(コア ダンプあり/なし) 3 通常は何の問題もなく動くアプリケーションが、メモリ 負荷が高くなると強制終了してしまう(コアダンプなし) 4 スローダウン 通常は何の問題もなく動くアプリケーション(sar、 iostat)が、負荷が高くなると計測タイミングの遅延が生 じる 通常は何の問題もなく動くアプリケーション(strace)が、 strace, lkst 2.5.2 負荷が高くなるとトレース対象のプロセス処理を遅延さ せてしまう I/O 負荷が高いとき性能がでない。 oprofile 2.5.3 5 フリーズ 性能情報採取コマンドを実行中にフリーズが発生した diskdump, Alicia 2.6.1 6 カーネルパニック 突然、カーネルパニックが発生した diskdump, Alicia, 2.7.1 objdump 7 ネットワーク障害 ネットワークリンクダウンが発生する ping, traceroute, netstat, 2.8.1 ifconfig, ethtool 8 ディスク障害 ディスク I/O エラーが発生(H/W RAID、S/W RAID、 StorageManager,swatch, LVM) mdadm,raidtool,df,lvm - 1-2 - 2.9.1、2.9.2、2.9.3 1.1 障害解析の一般的手順 エンタープライズシステムにおける、障害解析の際の一般的な手順を 図 1.1-1 に示す。 システム管理者 障害解析者 1. 準備 2. 稼働開始 障害 発生 3. 障害情報収集 2'. 稼働再開 障害情報 4. 初期切り分け 障害情報 障害情報から 解析可能? N 5. 再現手段確立 Y 6. 障害解析 障害原因 特定? N Y 回避策を適用 7. 回避策の検討、実施 本対策を適用(稼働環境のタイミングによる) 図 1.1-1 8. 本対策の検討、実施 障害解析概要フロー システム管理者は、障害発生時の情報収集に必要な準備(図中の 1)を行ってからシステ ムを稼働(2)する。障害発生時は、速やかに障害情報を収集(3)し、稼働を再開(2')す る。 障害解析者は収集された障害情報から、まず初期切り分け(4)により、ハード/OS/ミ ドル/アプリの切り分けを行う。切り分け後は、障害情報からの解析が可能かどうかを判 断し、不可能な場合は障害の再現手段を確立(5)する。次に、障害原因が特定できるまで 解析(6)を行う。 対策に関しては、エンタープライズシステムに於いては、システムを更新できるタイミ - 1-3 - ングが限られているため、本対策(8)の前に回避策(7)を実施することが多い。 本報告書では、主に太枠の部分に関して報告する。特に障害解析(6)については、障害 解析事例を用いて詳細に報告する。 1.2 準備 障害解析にあたり、万が一、障害が発生したとき十分な情報が取得できるようにいくつ かの準備を行うべきである。あらかじめ障害に対する準備をしておくと、障害対応の時間 の節約が期待できる。 (1) カーネルクラッシュダンプ取得準備 以下の点に注意する。 ・ ダンプデータ保存用パーティションのサイズは大丈夫か? 物理メモリサイズと同サイズではなく、余裕を持ったサイズ(約 1.5 倍を推奨)を用意 する必要がある。通常は OS インストール時にダンプ保存用パーティションを作成する。 運用時でパーティション作成が難しい場合は、ディスク増設などを検討する。 ・ ダンプ取得用ディレクトリは十分なサイズを持つか? diskdump の場合、/var/crash に取得したダンプを格納するので、そのディレクトリが 十分な空きディスク容量を持つか確認する。/var はログファイルが格納される場所なの で十分な空きディスク容量がない場合があるので注意が必要である。可能であれば /var/crash も十分な容量を持つ別パーティションにしておくのがよい。 ・ カーネルパニック時にダンプ採取する設定になっているか? cat /proc/sys/kernel/panic_on_oops を実行して 0 だった場合は、以下を実行しダンプを 取得できるようにする。恒久的に設定するには、/etc/sysctl.conf 中に kernel.panic_on_oops = 1 の行を追加する。 # echo 1 > /proc/sys/kernel/panic_on_oops ・ パニックを起こしてみて、ダンプが取れることを確認する。 # echo c > /proc/sysrq-trigger ないしは Alt-SysRq-C でダンプが取れることを確認する。 (2) カーネル設定 ・ CONFIG_MAGIC_SYSRQ=y になっているか? ‘y’になっていない場合、SysRq キーによるクラッシュダンプの取得やメモリ情報の取得 ができないので注意する。/boot/config-`uname -r` が当該 OS の設定ファイルなのでそ - 1-4 - れを確認する。SysRq キーの機能については/usr/src/linux/Docuemtation/sysrq.txt を 参照のこと。 実行時に SysRq キーを有効にするには下記を行う。 # echo "1" > /proc/sys/kernel/sysrq (3) アプリケーションクラッシュ取得準備 ・コアファイルのサイズ制限がかかっていないことを ulimit -c コマンドで確認する。もし もサイズが不足している場合は、ulimit -c unlimited を行う。恒久的に設定するには、 /etc/security/limits.conf 中に* soft core unlimited の行を追加し再ログインする。恒久的 に設定していない場合、ulimit コマンドで unlimited を設定したシェル以外でアプリケー ションを実行しても、その設定は反映されないことに注意する必要がある。 ・可能な限り gcc オプション-g を付けてコンパイルする。デバッグの時だけでなく、コア ファイル解析の際にもシンボルありで表示されるため、追跡が容易になる。 (4) oprofile を利用する場合は、kernel-debuginfo のインストール # rpm –qa| grep debuginfo で kernel-debuginfo がインストールされているか確認できる。 (5) アプリケーションのログの設定と監視 ・ アプリケーションによっては障害事項に関して独自のログを発行するものがある。障害 で停止する前に警告を発行する場合があるので、運用時に監視することによってあらか じめ障害にそなえることができる。 ・ 万が一障害が発生したとしても、アプリケーションログを取得するようにしておけば、 障害原因究明のヒントが得られるかもしれない。 1.3 障害情報収集および初期切り分け 障害が発生した直後の障害情報収集は重要であり、発生時の手順、更新された内容・環境 など調査し情報を残すと共に、可能な限り広範囲な障害情報を収集することが望ましい。 障害発生時のシステム状態を確認する為に mcinfo(MIRACLE LINUX)や、sysreport(Red Hat)、getinfo(Turbolinux)を利用して収集することも有効である。収集の後は、状態回復/ 復旧を行なうこと。 初期切り分けの判断材料として、/var/log/messages, /proc, dmesg 等の情報を確認するこ とが重要である。必要なログの取得が終了したなら、速やかに状態回復/復旧を目指すこと。 - 1-5 - 1.4 再現および障害解析 まず、障害発生時の状況として、障害解析可能な情報(例えば、コアダンプファイルや メモリダンプファイル)が保存されているかを確認する。 障害解析可能な情報が存在しない場合は、障害解析環境において障害を再現させる必要 がある。しかし実際には障害の再現は難しく、長時間掛かる場合も多い。更に再現しない 場合もあり、そのような場合には、稼働環境で追加情報収集の準備を行い、再現待ちをす る。 障害解析可能な情報が存在する場合および、障害の再現が可能な場合は、障害解析を行 う。障害解析作業としては、解析に必要な情報収集を行いながら切り分け作業を行い、障 害原因を追求して行く。障害事象によって使用する解析ツールが異なるため、どのような 障害事象の場合にどのようなツールを使うのが有効であるかなど、具体的な手法に関して は 2 章を参照のこと。 - 1-6 - 1.5 使用可能なツールとその分類 障害解析に有効なツールおよび関連ファイルを障害解析フェーズ毎に分類したものを 表 1.5-1 に示す。 表 1.5-1 項 機能分類 名称 障害解析に有効なツール/関連ファイルの分類 概要 番 1 ダンプ取得 diskdump 障害時にクラッシュダンプを 使用する解析フェーズ 備考 準備 (章番号) 情報 障害 収集 解析 ○ 3.6.1.1 ○ 3.6.1.2 ○ 3.6.1.3 ○ 3.6.1.4 ディスク上に採取する仕組 みである 2 netdump 障害時にクラッシュダンプを ネットワーク経由で採取する 為の仕組みである。 3 LKCD 障害時のメモリダンプ採取 機能およびメモリダンプ解析 ツールの提供する。 4 kdump 障害時に、セカンドカーネル を使用してダンプを採取する 仕組みである。 - 1-7 - 項 機能分類 名称 概要 番 5 mkdump 障害時に、ミニカーネルを使 使用する解析フェーズ 備考 準備 (章番号) 情報 障害 収集 解析 3.6.1.5 ○ 用してダンプを採取する仕組 みである。(kexec/kdump の 改良版) 6 システム情報取得 /var/log/messages 一般的なシステム情報を記 2.4 ○ 録したログファイル。 (システム全体) 7 /usr/include/asm/errno.h エラー番号の定義ファイル。 8 dmesg カーネルのログ用リングバッ ○ 2.3.1 ○ ファの表示および設定を行 なう。 9 lsmod ロードされているモジュール ○ の情報を一覧表示する。 10 lspci 全ての PCI バスとそこに接 ○ 続されている全デバイスの 情報を表示する。 11 top CPU およびメモリの使用量 ○ をプロセス単位で表示する。 12 ipcs IPC リソース情報を表示す ○ る。 13 sysctl /proc/sys/以下にリストされ ているカーネルパラメータを 設定する。 - 1-8 - ○ 2.5.2 項 機能分類 名称 概要 番 14 mpstat 使用する解析フェーズ 備考 準備 (章番号) /proc ファイルシステムが提 情報 障害 収集 解析 ○ 3.1 ○ MIRACLE 供する統計データのうち CPU 関連の情報を収集す る。 15 mcinfo 各種ログやハードウェア情 LINUX 報、インストールされている パッケージなどの情報を収 集する。 16 /proc/cpuinfo CPU に関する情報を表示。 17 /proc/stat カーネル/システムの統計情 ○ ○ ○ 報。 18 /proc/version カーネルのバージョン識別 ○ ○ 子文字列。 19 sysreport システムのハードウェアと構 ○ Red Hat Linux Fedora Core 成に関する情報を収集す る。 20 getinfo システムのハードウェアと構 ○ Turbolinux ○ 2.5.1、 2.5.2、 成に関する情報を収集す る。 21 sar /proc ファイルシステムが提 供するシステムに関する統 計データを収集する。 - 1-9 - 3.1 項 機能分類 名称 概要 番 22 システム情報取得 /proc/プロセス ID/stat 備考 準備 (章番号) プロセスの状態についての 情報 障害 収集 解析 ○ 情報。 ps で使われる。 (プロセス関連) 23 使用する解析フェーズ ps 実行されているプロセスの ○ 2.5.1 一覧を表示する。 24 pstree 実行中のプロセスをツリー形 ○ 式で表示する。 25 システム情報取得 free メモリの使用量と空き容量を 表示する。 (メモリ関連) 26 ○ vmstat 仮想メモリの統計情報を表 ○ 示する。 27 pmap 29 /proc/meminfo ○ 未使用および使用中のメモ ○ ○ ○ ○ 2.4.1 ○ 2.5.1、 3.1 リ量などメモリ情報を表示。 free で使われる。 30 /proc/sys/vm/overcommit_memory カーネル仮想メモリのアカウ ントモードを表示。 31 システム情報取得 iostat /proc ファイルシステムが提 供する統計データのうち I/O (I/O 関連) 処理に関する情報を収集す る。 32 fdisk パーティションテーブルの操 作をおこなう。 - 1-10 - ○ 項 機能分類 名称 概要 番 33 df ファイルシステムのディスク 使用する解析フェーズ 備考 準備 (章番号) 情報 障害 収集 解析 ○ 3.5.1 ○ 3.5.1 ○ 3.5.1 ○ 3.5.1 使用量と空き容量を表示す る。 34 lvm 複数のドライブをまとめて 「論理ボリューム」とし、 各 パーティションに割り振れ る。さらにこのユニットは、空 きの調整が必要となった時 に、パーティションに対して 追加や削除が行える。 35 raidtools S/W RAID 設定・管理が出 来るツールである。 36 mdadm 複数のディスクドライブやパ ーティションをまとめて 1 つ のファイルシステムとして利 用することができる。 37 DAVL ディスクのフラグメンテーショ ○ ン状態を可視化する。 38 システム情報取得 (ネットワーク ifconfig ネットワークインタフェイスの 表示と設定を行なう。 - 1-11 - ○ 3.4.1 項 機能分類 名称 概要 番 39 関連) ping ICMP パケットをネットワー 使用する解析フェーズ 備考 準備 (章番号) 情報 障害 収集 解析 ○ 3.4.1 ○ 3.4.1 ク上のホストに送り応答結果 を表示する。 40 netstat ネットワーク接続および経路 に関する情報を表示する。 41 host DNS を使いホスト名の検索 ○ をおこなう。 42 route IP 経路テーブルの表示およ ○ び設定をおこなう。 43 traceroute あるホストから別のホストま ○ 3.4.1 ○ 3.4.1 でのネットワーク経路を表示 する。 44 ethtool ネットワークインタフェースの 状況を調査する。 45 46 トレーサ strace ユーザ空間のプラグラムが (システムコール/ 発行したシステムコールとシ ライブラリ) グナルをとらえて記録する。 ltrace プログラムから共有ライブラ リへの関数呼び出しを記録 する。 - 1-12 - ○ ○ 2.3.1、 2.5.2 ○ ○ 2.3.1、 2.4.1、 2.4.2 項 機能分類 名称 概要 番 47 トレーサ LKST Linux カーネルの処理をトレ (カーネル内 ースするツール。カスタマイ イベント) ズ機能をもつ。 48 LTT 組み込み系向けの Linux カ 使用する解析フェーズ 備考 準備 (章番号) 情報 障害 収集 解析 ○ ○ ○ ○ 2.5.1、 2.5.2 ーネルの処理をトレースする ツール。 49 プロファイラ OProfile カーネルおよびユーザプロ ○ 3.2.1 グラムのハードウェアイベン トのプロファイリングを行う。 コールグラフ機能、ソースコ ードとの対比などを行う高機 能なプロファイラ。 50 51 デバッガ readprofile カーネルプロファイラ ○ 3.2.6 gdb プログラムが実行中もしくは ○ 2.5.2 クラッシュした時にその プロ (アプリケーション) グラムの内部で何が行われ ていたかを調べるツール。 52 デバッガ (カーネル) kdb カーネル の 実行を トレ ース し、メモリやデータ構造を調 査するツール。 - 1-13 - ○ 項 機能分類 名称 概要 番 53 kgdb 使用する解析フェーズ 備考 準備 (章番号) 情報 障害 収集 解析 他のホストの gdb から ○ リモート操作できるカーネル デバッガ 54 ダンプ解析 crash UNIX の crash ツールのイ ○ 3.6.2.1 ○ 3.6.2.1 ○ 3.6.2.1 ンターフェースをベースに作 成されたツール 55 lcrash LKCD で採取されたダンプ を編集するために作成され たツール 56 Alicia Linux カーネルダンプ解析 ツールである crash/lcrash をラッピングしたダンプ解析 ツール 57 ロガー MRTG SNMP によりネットワークや ○ システムを監視しグラフ表示 する。 58 Nagios システムとネットワークの監 視アプリケーション。ホストや サービスを監視し、障害発生 に対し警告。 - 1-14 - ○ 1.5.1 3 章で評価するツールについて (1) パフォーマンス監視ツール:sar、 iostat、 mpstat sysstat パッケージに含まれるこれらのツールは、CPU 利用率や I/O 負荷の計測に良 く利用されるものであるが、システムの負荷が高い状況下ではうまくデータを取得でき ない場合があり、監視ツールとして利用上の注意が必要である。どのような負荷タイプ で注意が必要か、回避策としてどのような方法が可能かについて評価を行い、より安定 して必要なデータを取得できる利用技術を提供する。 (2) プロファイラ:OProfile、 readprofile OProfile はカーネルモードおよびユーザモードでのハードウェアイベントのプロファ イリングを行う。コールグラフ機能、ソースコードとの対比の機能などがあり高機能で ある。readprofile はカーネルプロファイリングの機能を提供する。 (3) システムコールトレーサ:strace、 ltrace これらのツールは、主にアプリケーション障害の解析用として広く使われており、非 常に有効なツールである。使用される場面も多岐にわたると考えられるが、どの程度ま での負荷ならば問題なく使用できるか評価を行い、実際に障害解析で使用する際のガイ ドラインを提供する。 (4) ネットワーク情報収集ツール:ethtool、 ifconfig、 netstat、 ping、 traceroute、 Bonding ネットワーク設定、監視、解析用として標準的に取り込まれている機能であり、様々 な状況下において有効なツールであると考えられるが、実際の使用方法について情報を 提供する。 (5) ディスク情報収集ツール:df、 raidtools、 mdadm、 smartmontool、 LVM2 ディスク環境設定、監視、解析用として一般的に使われており、様々な状況下におい て有効なツールであると考えられるが、実際の使用方法について情報を提供する。 (6) ダンプツール: (採取ツール)diskdump、 netdump、 LKCD、 kdump、 mkdump (解析ツール)crash、 lcrash、 Alicia、 mdb ダンプツールは、大きく分けてダンプをディスクに吐き出すためのダンプ採取ツール と、ダンプをディスクから読み込み解析を容易にするためのダンプ解析ツールの二つに 分類できる。それぞれ複数のツールが利用可能であるが、ダンプツールに関しては整理 された情報が公開されていないため、各ツールの使用方法やツール間の機能比較等につ いて情報を提供する。 - 1-15 - 2 障害解析手法と考察 2.1 障害事例の最近の傾向 国内SI/OSベンダ数社のサポートセンタにて、この一年間最近の問合せの件数を合計(約 200 件)し、事象分類した結果を 図 2.1-1 に示す。 事象分類 3% 2% 1% 5% 6% 31% 10% 10% エラーメッセージ関連 ディスク障害 アプリ異常終了 フリーズ パニック ネットワーク障害 起動障害 スローダウン インストール障害 リブート 17% 15% 図 2.1-1 障害(事象分類) このグラフからはエラーメッセージ関連の問い合わせが多いことがわかる。これは、シス テムから表示されるメッセージが、ユーザには障害(問題)であるかが判断出来ないためと考 えられる。今後は、表示されるメッセージの情報に関しても整備が必要なのでは、と考え させられる結果である。 - 2-1 - 2.2 一般的な障害解析手法 以下、代表的な障害事象に関して、事象毎にそれぞれ代表的な障害解析手法を示す。 2.2.1 エラーメッセージ関連 エラーメッセージの場合、障害情報収集の一部として下記を行う。 (1) エラーメッセージの確認 異常終了時にエラーメッセージが出力されていないか確認し、出力されていればメモ する等して保存しておく。 (2) アプリケーションログファイルの確認 アプリケーションログがあれば参照し、エラーが出力されていないかどうか確認する。 エラーが出力されていればメモする等して保存しておく。 (3) コアダンプファイルの確認 異常終了時にコアダンプファイルが出力されていないか確認し、出力されていれば別 ディスク上に書き出す等して保存しておく。 (4) システムログファイルの確認 異常終了時のシステムログ(/var/log/messages 等)を確認し、同アプリケーションの エラーが出力されていないかを確認し、出力されていればメモする等して保存してお く。 障害解析手法としては、主に表 2.2-1 に示すやり方がある。 表 2.2-1 エラーメッセージの障害解析手法 # 手法名称 手法概要 1 類似障害検 Red Hat 社の Bugzilla(https://bugzilla.redhat.com/bugzilla/) 索 を代表とするインターネット上のサイトや社内の障害事例等を 検索し、類似障害が報告されていないかを確認する。 2 アプリケー アプリケーションのマニュアル等でログないしメッセージを確 ションログ 認する。 ファイルの 解析 3 環境情報の どのような環境でエラーメッセージないしはログ情報が取得さ 取得 れたかを確認する。 表 2.2-2 の代表的な障害解析手法を用いた、エラーメッセージからの障害解析フローを 図 2.2-2 に示す。 - 2-2 - 解析開始 1. 類似障害検索 N 解決 エラーメッセ ージあり? Y 2. エラー解析 解決 再現手段確立 N 再現可? Y 3. 最新版試行 解決 再準備 再現待ち 図 2.2-1 解析終了 エラーメッセージの障害解析フロー - 2-3 - 2.2.2 アプリケーション異常終了 アプリケーション異常終了の場合、まず障害情報収集の一部として下記を行う。 (1) エラーメッセージの確認 異常終了時にエラーメッセージが出力されていないか確認し、出力されていればメモ する等して保存しておく。 (2) アプリケーションログファイルの確認 アプリケーションログがあれば参照し、エラーが出力されていないかどうか確認する。 エラーが出力されていればメモする等して保存しておく。 (3) コアダンプファイルの確認 異常終了時にコアダンプファイルが出力されていないか確認し、出力されていれば別 ディスク上に書き出す等して保存しておく。 (4) システムログファイルの確認 異常終了時のシステムログ(/var/log/messages 等)を確認し、同アプリケーションの エラーが出力されていないかを確認し、出力されていればメモする等して保存してお く。 障害解析手法としては、主に 表 2.2-2 に示す 5 通りのやり方がある。 表 2.2-2 アプリケーション異常終了の障害解析手法 # 手法名称 手法概要 1 類似障害検索 Red Hat 社の Bugzilla (https://bugzilla.redhat.com/bugzilla/) を代表とするインターネット上のサイトや社内の障害事例等 を検索し、類似障害が報告されていないかを確認する。 2 コアダンプ解析 異常終了時のコアダンプが取れていた場合、デバッガを用いて コアダンプを解析することで障害箇所を特定する 3 環境変更試行 アプリケーションの版を変えたり、CPU/ディスク/メモリ 等の条件を変えたりして、同様の現象が起こるか確認する 4 トレーサ解析 ライブラリ/システムコールトレーサを用いて障害原因を特 定する 5 デバッガ解析 デバッガを用いて更に詳細な障害原因の追跡を行う 表 2.2-2 の代表的な障害解析手法を用いた、アプリケーション異常終了の障害解析フロ ーを 図 2.2-2 に示す。 - 2-4 - 解析開始 1. 類似障害検索 N 解決 コアダンプ 出力あり? Y 2. コアダンプ解析 解決 再現手段確立 N N N ソース入手 可能? 再現可? Y 3. 最新版試行 解決 4. トレーサ解析 解決 -g 付きでコ ンパイル済 み? Y Y -g 付けてリビルド※ ※ configure ス ク リ プ ト や Makefile の修正が必要な 場合が多い。 5. デバッガ解析 解決 再準備 再現待ち 図 2.2-2 解析終了 アプリケーション異常終了の障害解析フロー - 2-5 - 2.2.3 スローダウン スローダウンの場合、まず障害情報収集の一部として下記を行う。 (1) スローダウン障害発生状況時の確認 いつから、どのようなクライアント側アプリケーション操作によりスローダウンに気 がついたかを確認し、必要に応じてスクリーンショット等を保存しておく。単一のク ライアントのみで発生した障害か複数のクライアントで広範囲に発生しているかにつ いても、原因の特定に有効な情報である。 (2) ネットワーク接続の確認 複数のクライアントで障害が発生しているが、一部のネットワークで障害が集中的に 発生している疑いがある場合には、サーバやルータへの応答テストやネットワーク負 荷履歴の確認、ネットワーク機器のログの確認をおこない、異常が出力されていれば メモする等して保存しておく。 (3) アプリケーションのログファイルの確認 複数のクライアントで障害が発生しておりサーバ側アプリケーションで障害発生の疑 いがある場合には、アプリケーションのログファイルに警告やエラーが出力されてい ないか確認し、出力されていればメモする等して保存しておく。 (4) サーバの負荷状況の確認 サーバのプロセス状況や負荷状況を確認し、通常と異なる場合にはメモする等して保 存しておく。 (5) システムログファイルの確認 サーバのシステムログ(/var/log/messages 等)を確認し、アプリケーションのエラー が出力されていないかを確認し、出力されていればメモする等して保存しておく。 障害解析手法としては、主に 表 2.2-3 に示す 6 通りの方法がある。 表 2.2-3 スローダウンの障害解析手法 # 手法名称 手法概要 1 類似障害検索 Red Hat 社の Bugzilla (https://bugzilla.redhat.com/bugzilla/)を代表とするイ ンターネット上のサイトや社内の障害事例データベース等を 検索し、同様な障害が報告されていないかを確認する。 2 ログ解析 障害時のアプリケーションログやシステムログに詳細な記録 が取れていた場合、それぞれのケースで固有の方法により解析 することで障害箇所を特定する。 3 環境変更試行 アプリケーションの版を変えたり、CPU/ディスク/メモリ等 の条件を変えてみて、同様の現象が起こるか確認する 4 トレーサ解析 ライブラリ/システムコールトレーサを用いて障害原因を特 - 2-6 - 定する 5 6 プロファイル プロファイラを用いて関数の呼び出し頻度や処理時間等を分 解析 析し障害原因を特定する デバッガ解析 デバッガを用いて更に詳細な障害原因の追跡を行う - 2-7 - 表 2.2-3 の代表的な障害解析手法を用いた、スローダウンの障害解析フローを 図 2.2-3 に示す。 解析開始 N 複数クライアン トで異常あり? 単体問題として 障害解析 Y ネットワーク に異常あり? Y ネットワーク 障害解析手順へ N 疑わしい要因 の選定 1. 類似障害検索 N 解決 アプリログに 異常あり? Y 2. ログ解析 解決 再現手段確立 N N N ソース入手 可能? 再現可? Y 3. 環境変更試行 解決 4. トレーサ解析 解決 -g 付きで コンパイル済み? Y Y -g 付けてリビルド※ ※ configure ス ク リ プ ト や Makefile の修正が必要な 場合が多い。 5. プロファイル解析 6. デバッガ解析 解決 解決 再準備 再現待ち 図 2.2-3 スローダウンの障害解析フロー - 2-8 - 解析終了 2.2.4 フリーズ システムがフリーズした場合、次のような手順で解析を行う。 (1) コンソールからのコマンド入力が可能であるかを調べる。 コマンドにより、システム状態を解析し、対応を行う。→ 「スローダウン」対応 (2) コマンドの応答がない場合、または、異常が解消されない場合、 SysRqキーか、NMIインターフェースより、ダンプ採取を行う。 (3) 採取したダンプより、ダンプ解析ツールを使用して解析を行う。 次のような観点でダンプ解析を行う。 (a)CPU使用率の高いプロセスがあるかを調べる。ある場合は、そのプロセスがどのよう な処理を行っているかを調べる。 (b)システムの資源(メモリ、スレッド等)が枯渇していないかを調べる。枯渇している 場合は、どのプロセスが浪費しているか、そのプロセスが異常な処理を行っていない かを調べる。 (c)Run queueにキューされているプロセスが異常に多くないかを調べる。 (d)I/O Request queue に異常に多くの I/O 要求がキューされていないかを調べる。 (e)ロックをかけたままのプロセスの処理に誤りはないか、ロック開放待ちのプロセスが 異常な処理を行っていないかを調べる。 (f)停止しているプロセスの処理が正しいか、フラグのクリアミスでクリア待ちのままと なっていないかを調べる。 (g)ハードウェアに異常があるようなメッセージがログされていないかを調べる。 (h)カーネルプロセスの処理が異常に多くないかを調べる。 表 2.2-4 (スワップ処理等) フリーズの障害解析手法 # 手法名称 手法概要 1 類似障害検索 Red Hat 社の Bugzilla (https://bugzilla.redhat.com/bugzilla/) を代表とするインターネット上のサイトや社内の障害事例デ ータベース等を検索し、同様な障害が報告されていないかを確 認する。 2 ダンプ解析 障害時に採取したダンプの解析を行うことで、障害箇所を特定 する。 3 ログ解析 障害時のアプリケーションログやシステムログに詳細な記録 が取れていた場合、それぞれのケースで固有の方法により解析 することで障害箇所を特定する。 4 環境変更試行 アプリケーションの版を変えたり、CPU/ディスク/メモリ 等の条件を変えてみて、同様の現象が起こるか確認する - 2-9 - 解析開始 解決 1. 類似障害検索 コンソール 入力に応答 があるか? Y スローダウン 障害解析手順へ N N SysRq キー 入力可? Y 2. ダンプ解析 解決 3. ログ解析 解決 4 最新版試行 解決 再準備 再現待ち 図 2.2-4 フリーズの障害解析フロー - 2-10 - 解析終了 2.2.5 カーネルパニック カーネルパニックの場合、次のような手順で解析を行う。 (1) カーネルパニックのダンプが採取されているかを調べる。 カーネルパニックのダンプが採取されていない場合、コンソールに出力されたパニック メッセージ、ログファイルから解析を行う。 (2) 採取されたダンプから、ダンプ解析ツールを使用して解析を行う。 (3) カーネルが停止したエラーの種類が何であるかを調べる。 (4) カーネルが停止したアドレスがどこであるかを調べる。 (5) カーネルソースコードより、停止したアドレスでどのような処理を行っていたかを解析 する。ソースコードとダンプのデータを照合しながら、ロジック追求を行う。 表 2.2-5 カーネルパニックの障害解析手法 # 手法名称 手法概要 1 類似障害検索 Red Hat 社の Bugzilla (https://bugzilla.redhat.com/bugzilla/) を代表とするインターネット上のサイトや社内の障害事例デ ータベース等を検索し、同様な障害が報告されていないかを確 認する。 2 ダンプ解析 採取したダンプの解析を行う。 3 ログ解析 障害時のアプリケーションログやシステムログに詳細な記録 が取れていた場合、それぞれのケースで固有の方法により解析 することで障害箇所を特定する。 4 環境変更試行 アプリケーションの版を変えたり、CPU/ディスク/メモリ 等の条件を変えてみて、同様の現象が起こるか確認する - 2-11 - 解析開始 1. 類似障害検索 N 解決 ダンプ採取 されたか? Y 2. ダンプ解析 解決 3. ログ解析 解決 4 最新版試行 解決 再準備 再現待ち 図 2.2-5 解析終了 カーネルパニックの障害解析フロー - 2-12 - 2.2.6 ネットワーク障害 ネットワーク障害発生時の対処法のフローとして以下のような手順を提案する。 NIC カード毎に IP アドレスが割り振られている環境、もしくはネットワーク冗長化され た環境において、ネットワーク障害発生時の対処法のフローとして以下のような手順を奨 める。 開始 障害発生通知 1 1. pingテスト (IPアドレス) N Y 2 2.pingテスト (FQDN) 8.ifconfigにて 設定確認 N Y N Y 6.参照DNSの 設定確認 4. netstat, traceroute等 による確認 9.ethtoolにて 稼動確認 N Y 12.ネットワーク 設定変更 N Y N Y 7. 管理者 へ再問合せ 10.管理者へ 再問合せ N Y Y 7.参照DNSの 設定変更 5.管理者へ問合せ 終了 2 N 2 2 11.物理的構成確認 1 図 2.2-6 ネットワーク解析フローチャート - 2-13 - 1 1 1. 疎通テスト-ping-(ip アドレス) この段階では、ping による ip アドレスを使用した疎通検証のみを行う。しかし、対 PC だけではなくて、必要に応じて、ネットワークルータ等に対して疎通検証を行なう。 2. 疎通テスト-ping-(FQDN) この段階では、IP アドレスを使用した疎通テストは終了している為、DNS サーバを介し た名前解決が出来ることを確認する為に、ping を使用して疎通検証を行なう。必要に応じ て、ネットワークルータ等に対して疎通検証を行なう。 3. netstat,traceroute による確認 netstat,traceroute によるネットワーク状態や、ルートの確認を行なう。 4. 管理者への問合せ netstat,traceroute 等による確認を行なったが反応がない場合、ネットワーク管理者へ問 合せをする。 5. 参照 DNS の設定確認 /etc/resolv.conf,nslookup による参照 DNS サーバの確認を行なう。 6. 参照 DNS が正しいか管理者へ確認 通知された設定内容が正しいものかを確認するために、ネットワーク管理者へ問合せを 行なう。 7. 参照 DNS の設定変更 参照 DNS サーバの設定/変更を行なう。変更した後、再度、名前解決したことを確認す る。 8. ネットワーク設定確認 ifconfig コマンドを使用したネットワークインターフェースの稼動状態確認を行なう。 9. インターフェース稼動確認 Ethtool を使用したネットワークインターフェースの稼動状態確認を行なう。確認項目は、 *Link detected:”(最終行)が”Yes”であれば、管理者への問合せを行い、”No”であれば、、 物理構成確認を行なう。 10. 管理者への構築環境の再問合せ 何が違っているのか判断できないので、再度、ネットワーク管理者へ問合せし、ip アド レス、サブネットマスクなどの情報を確認する 11. 物理構成確認 物理的な障害が発生していると判断される。設定の問題ではなく、物理的に接続できて いないと判断されるため、使用しているネットワーク構成を物理的な見解で見直す必要が ある。もしくは、敷設されているネットワークが使用可能状態であるかも管理者に対して 確認する。 12. ネットワーク設定変更 入力ミスなどの問題による設定不良と思われる為、設定の変更、追加を行なう。 - 2-14 - 2.2.7 ディスク障害 ディスク障害時の対処方法切り分けについて述べる。以下の図は、ディスク障害が発生 した時の対処フローチャートである。 開始 障害発生通知 1.状況確認 (ログの確認) N Y 2.状況確認 3.shutdown N 8.強制 Power Off Y Y N 10. ディスク検出 確認 N 9.電源ON Y 4.復旧の実施 N 11.復旧の実施 N Y Y 5.復旧確認 N 12.復旧確認 N Y Y 6.復旧 6.復旧 7.ディスク交換 終了 図 2.2-7 解析フローチャート - 2-15 - 7.ディスク交換 1. syslog の確認が出来る状況にあるか確認する。 2. syslog に記録されている内容を確認し、どのようなディスク障害が発生しているか確認 する。 3. システムを停止し、fsck が行なえる状態にする。 4. fsck によるディスク復旧を行なう。 5. 復旧確認を行なう。この場合、システムを reboot させ障害発生したボリュームがマウ ントできるか等を行なう。 6. 障害が発生したボリュームがマウントできていれば、復旧したものとする。 7. fsck による復旧の失敗、fsck の検証はパスしたがマウントできなかったことから、ディ スク故障と判断し新品ディスクに交換する。 8. システムがハングアップしている状態であり、全ての操作が出来ないことから、強制的 に電源 OFF する。 9. 電源 ON し、fsck が出来る状態にする。 10. BIOS もしくは、dmesg によるディスクの検出ができているか確認する。 11. Rescue モードによる復旧(fsck)を実施する。 12. 復旧確認を行なう。この場合、システムをリブートさせ障害発生したボリュームがマウ ントできるか等を行なう。 - 2-16 - 2.3 エラーメッセージ関連 2.3.1 スレッド生成不可(man ページにないエラー)が発生する障害の解析 アプリケーションのパラメータ設定によりスレッド生成数を増やすと、man ページに記 述のないスレッド生成エラーが表示される障害に関して、解析と対策を以下に報告する。 2.3.1.1 概要 本障害とその対策の概要を 表 2.3-1 に示す。 表 2.3-1 高負荷時アプリケーション異常終了の概要 番号 2.3.1 現象 パラメータ設定によりスレッド生成数を増やすと man ページにないス 発生日 2005/xx/xx 解決日 2005/xx/xx レッド生成エラーが表示される 分類 エラーメッセージ関連 発生環境 OS Fedora Core 3 CPU Xeon 2.4GHz×1 メモリ 2GByte ハードディスク IDE 120GByte ネットワーク Intel 82545EM Gigabit Ethernet 原因 メモリ不足によるスレッド生成の失敗 対策 スレッドが使用するスタック領域の縮小(縮小して問題ないかどうか は、アプリに依存する) 解析手法 ltrace による解析~man 確認、ヘッダファイル解析によるエラーコー ドの確認~strace による解析 2.3.1.2 障害情報収集と初期切り分け エラーメッセージ関連の障害発生時はまず、エラーメッセージをメモする等して記録し ておく。また、どのような操作を行った場合にその障害が発生したかを記録しておく。 初期切り分けでは、エラーメッセージから障害原因が特定できないかを判断する。また Web 上でエラーメッセージを検索する等して同様な障害報告がないかを確認する。 本事例では、エラーメッセージから障害の内容は確認できるのだが、何故その障害が発 生するのか、どう対策すれば良いかが分からなかった。このため、障害解析環境で再現さ せて解析を行う。 2.3.1.3 再現手段の確立 まず、現象が再現するかどうかを確認する。再現手順は、以下の通り。 - 2-17 - a. アプリケーションをスレッドパラメータ付きで起動する。この場合のパラメータ値は、 障害情報収集で取得した操作内容と同じものを使用する。本事例では 400 スレッドでエ ラーメッセージ「pthread_create failed (id: 380)」が出力されるとのことだった。 $ thread_app --thread=400 b. エラーメッセージが出力されることを確認する。 c. エラーメッセージが出力されたら、Ctrl+C 等によってアプリケーションを終了する。 上記手順により、障害が再現することを確認する。 2.3.1.4 解析 (1) ltrace による解析 障害が再現できたので、次のステップとして障害箇所の切り分けを行うため、システム コール/ライブラリコールをトレースする。まずライブラリコールトレーサを用い、更に システムコールレベルの詳細な情報が必要な場合にシステムコールトレーサを使う。ライ ブラリコールトレーサ ltrace 経由でアプリケーションを起動して障害を再現する手順は、 以下の通り。 a. ltrace 経由でアプリケーション起動し、エラーメッセージが出力されるのを待つ $ ltrace -f -o ltrace.log thread_app --thread=400 b. エラーメッセージが出力されたら、Ctrl+C 等によって ltrace を終了する。 トレース結果を確認する際には、まずエラーを返しているシステム/ライブラリコール に着目して、当たりをつける。また障害箇所が特定できる場合は、そこから遡って見て行 き、障害の原因となるシステム/ライブラリコールを特定できるかどうかを確認する。 本事例では、エラーメッセージが出力されているため、そのメッセージを検索すれば良い。 ltraceのトレース結果を、図 2.3-1 に示す。 $ ltrace -f -o ltrace.log thread_app --thread=400 1. 出力エラーメッセージを検索 :(省略) 23865 pthread_create(0x804a5ec, 0, 0x8048520, 377, 0x6f9378) = 0 23865 pthread_create(0x804a5f0, 0, 0x8048520, 378, 0x6f9378) = 0 2. 直前の pthread_create コールが失敗し 12 が返 っている 23865 pthread_create(0x804a5f4, 0, 0x8048520, 379, 0x6f9378) = 0 23865 pthread_create(0x804a5f8, 0, 0x8048520, 380, 0x6f9378) = 12 23865 printf("pthread_create failed (id: %d)\n", 380) = 32 3. そ の 前 の pthread_create コ ー ル は成功している 23865 pthread_join(0xb7fefbb0, 0, 0x8048520, 380, 0x6f9378 <unfinished ...> 23865 --- SIGINT (Interrupt) --- 図 2.3-1 エラーメッセージ出力付近の ltrace 結果 - 2-18 - エラーメッセージ出力前の pthread_create 関数が 12 を返しており、その前までの pthread_create は 0 を返している。 (2) man 確認、ヘッダファイル解析によるエラーコードの確認 man で確認すると、pthread_create は正常時は 0 を返すことが分かるので、12 を返して いる pthread_create は何らかの要因で失敗したことが分かる。 次にエラーコード 12 の意味を調べる。man ページには pthread_create の返すエラーコ ードが EXXX の形式で記述されているが、数値は記述されていないため、標準ヘッダファ イル(/usr/include/asm/errno.h)を参照する。 $ cat /usr/include/asm/errno.h :(省略) #define ECHILD 10 /* No child processes */ #define EAGAIN 11 /* Try again */ #define ENOMEM 12 /* Out of memory */ #define EACCES 13 /* Permission denied */ :(省略) 図 2.3-2 エラーコード番号 12 の定義(定義ファイルの抜粋) 図 2.3-2 より、エラーの意味は「メモリ不足」だったことが分かるが、pthread_createの manページにはENOMEMに関する記述はなく、どのような場合にメモリ不足エラーになる のかが不明である。 (3) strace による解析 より詳細な解析を行うため、strace で再度トレースを行う。システムコールトレーサ strace 経由でアプリケーションを起動して障害を再現する手順は、以下の通り。 a. strace 経由でアプリケーション起動し、エラーメッセージが出力されるのを待つ $ strace -f -o strace.log thread_app --thread=400 b. エラーメッセージが出力されたら、Ctrl+C 等によって strace を終了する。 straceのトレース結果を 図 2.3-3 に示す。 - 2-19 - $ strace -f -o strace.log thread_app --thread=400 1. 出力エラーメッセージを検索 :(省略) 24252 mmap2(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...> 24630 futex(0x6f97ac, FUTEX_WAIT, 2, NULL <unfinished ...> 24252 <... mmap2 resumed> ) = 0xbe7ff000 24252 mprotect(0xbe7ff000, 4096, PROT_NONE) = 0 2. エ ラ ー メ ッ セ ー ジ 出 力 直 前 の mmap2 コールが ENOMEM を返し ている 24252 clone(child_stack=0xbefff4c8, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND 3. エラーを返す mmap2 コールの前 は、mmap2, futex, mprotect, clone NE_DETACHED, parent_tidptr=0xbefffbf8, {entry_number:6, コールが繰り返されており、この4 base_addr:0xbefffbb0, つ の シ ス テ ム コ ー ル が limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, pthread_create に対応すると考えら れる seg_not_present:0, useable:1}, child_tidptr=0xbefffbf8) = 24631 |CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|CLO 24252 mmap2(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...> 4. ENOMEM になる前の mmap2 コ ー ル で は 、 毎 回 8,392,704 ( 約 24252 <... mmap2 resumed> ) = 0xbf000000 8MByte)のメモリを確保しており、 最後に成功した mmap2 コールでは 24252 mprotect(0xbf000000, 4096, PROT_NONE) = 0 0xbf000000 のポインタ値が返って 24252 clone(child_stack=0xbf8004c8, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND いる 24631 futex(0x6f97ac, FUTEX_WAIT, 2, NULL <unfinished ...> |CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|CLO NE_DETACHED, parent_tidptr=0xbf800bf8, limit:1048575, seg_32bit:1, contents:0, {entry_number:6, base_addr:0xbf800bb0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xbf800bf8) = 24632 24252 mmap2(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...> 24632 futex(0x6f97ac, FUTEX_WAIT, 2, NULL <unfinished ...> 24252 <... mmap2 resumed> ) = -1 ENOMEM (Cannot allocate memory) 24252 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 24252 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x868f000 24252 write(1, "pthread_create failed (id: 380)\n", 32) = 32 24252 futex(0xb7fefbf8, FUTEX_WAIT, 24253, NULL) = -1 EINTR (Interrupted system call) 24252 --- SIGINT (Interrupt) @ 0 (0) --- 図 2.3-3 エラーメッセージ出力付近の strace 結果 Linux では、各スレッドのメモリ領域は親プロセスの空間を共有する。また、IA-32 アー キテクチャの場合、各プロセスで使用できるメモリ空間は 3GByte であり、その後ろの 1GByte はカーネル空間となっている(カーネル空間の先頭は 0xC0000000)。 注)ただし、Red Hat 系のカーネル(Fedora Core 3 も含む)で、カーネルオプション CONFIG_X86_4G が有効になっている場合は、 プロセス空間が 4GByte までに拡張される。 - 2-20 - 図 2.3-3 から、スレッド生成に伴うメモリ確保であるmmapの返り値が約 8MByte毎に増 えてゆき、カーネル空間付近のポインタ値 0xbf000000 を返していることから、プロセス空 間を使い切ってしまったことが分かる。また、表示されたエラーメッセージ「pthread_create failed (id: 380)」からスレッド数を 380 と仮定しメモリ使用量を算出すると、380× 8,392,704≒3GByteとなり、プロセス空間を使い切るだけのメモリを確保していることが推 測できる。 また、各スレッドのスタックサイズは ulimit で制限されるプロセススタックサイズと同 じである(ただし、これは使用している pthread ライブラリおよびそのコンパイル条件に 依存する)ため、ulimit コマンドでスタックサイズ値を確認する。 $ ulimit -s 8192(8MByte)であり、メモリ確保値と 合致する 8192 この結果、スレッド毎のメモリ確保容量≒スタックサイズであることも確認できる。 2.3.1.5 対策 対策案としては、スレッド毎のメモリ確保容量を少なくすることが考えられる。このた めには、各スレッドが使用するスタック領域を縮小すれば良い。ただし、以下の点に注意 する必要がある。 (1) どの程度のスタック領域でアプリケーションが正常に動くのかは、アプリケーションに 依存する (2) 使用している pthread ライブラリおよびそのコンパイル条件により、スレッドのスタッ ク領域を変更できない場合がある このような場合は、対策が可能であることを確認し、その対策によって障害が解消され ることを確認した後で、更に評価環境で運用評価を行う必要がある。 スレッドのスタック領域を変更する手順は、以下の通り。 a. ulimit コマンドでスタック領域を変更する(下記では、2MByte に縮小) $ ulimit -s 2048 b. ulimit コマンドを実行したシェル上でアプリケーションを起動する $ thread_app --thread=400 上記対策によってエラーメッセージが出力されなくなることを確認し、運用評価を行っ た後に本対策とした。 - 2-21 - 2.3.1.6 付録~再現用アプリケーションのソースコード 本事例を再現させるためのアプリケーション(thread_app)のソースコードは、下記の 通り。 #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *loop(void *tindex) { int i, timer = 3; for (;;) fgetc(stdin); } int main(int argc, char *argv[]) { int tnum, i; pthread_t *t; char *opt_head = "--thread="; if (argc != 2 || strstr(argv[1], opt_head) == NULL || strlen(argv[1]) <= strlen(opt_head)) { printf("app %sN\n", opt_head); exit(1); } tnum = atoi(argv[1] + strlen(opt_head)); t = calloc(tnum, sizeof(pthread_t)); /* create tnum threads */ for (i = 0; i < tnum; i++) { if (pthread_create(&t[i], NULL, loop, (void*)i)) { printf("pthread_create failed (id: %d)\n", i); tnum = i - 1; break; } } - 2-22 - /* wait terminate tnum threads */ for (i = 0; i < tnum; i++) { pthread_join(t[i], NULL); } exit(0); } - 2-23 - 2.4 アプリケーション異常終了 2.4.1 高負荷時にアプリケーションが異常終了する障害の解析(コアダンプな し) 通常の負荷だと問題なく動作するアプリケーションが、メモリ高負荷な状況下では異常 終了する障害に関して、解析と対策を以下に報告する。 2.4.1.1 概要 本障害とその対策の概要を 表 2.4-1 に示す。 表 2.4-1 高負荷時アプリケーション異常終了の概要 番号 2.4.1 現象 通常負荷時は問題なく動作するアプリケーションが、メモリ負荷が高く 発生日 2005/xx/xx 解決日 2005/xx/xx なると異常終了してしまう 分類 アプリケーション異常終了 発生環境 OS Fedora Core 3 CPU Xeon 2.4GHz×1 メモリ 2GByte ハードディスク IDE 120GByte ネットワーク Intel 82545EM Gigabit Ethernet 原因 メモリ確保後のポインタ値確認処理抜け(アプリケーションのバグ) 対策 メモリ確保後のポインタ値確認処理を追加 解析手法 ltrace による解析~ソースコードの解析 2.4.1.2 障害情報収集と初期切り分け アプリケーション異常終了の障害発生時はまず、エラーメッセージが出ているか確認し、 出ていればメモする等して記録しておく。また、どのような操作を行った場合に、その障 害が発生したかを記録しておく。 設定によってはコアダンプファイルが出力される場合があるので、出力されていれば別デ ィスクに保存しておく。 エラーメッセージが出力されている場合、その文字列の意味から障害原因が特定できな いかを判断する。また Web 上でエラーメッセージを検索する等して同様な障害報告がない かを確認する。 本事例では、エラーメッセージ、コアダンプファイル共に出力されていなかったため、 両者からの解析を行うことができなかった。このため、障害解析環境で再現させて解析を 行う。 - 2-24 - 2.4.1.3 再現手段の確立 まず、現象が再現するかどうかを確認する。再現手順は、以下の通り。 a. 高負荷状況作成ツール stress によりメモリ高負荷状況を再現する際に、stress 自身が kill されないようにするため、メモリのオーバーコミットを禁止する設定を行う(スーパー ユーザで行う必要あり) # echo 2 > /proc/sys/vm/overcommit_memory b. stress によって、メモリ負荷が高い状況を再現する メモリ負荷の設定は再現環境マシンのメモリ/スワップ容量および、そこで稼働中のプ ロセスでのメモリ使用状況に依存する。障害発生時のメモリ負荷情報が記録されている 場合はその負荷となるように stress のパラメータを設定し、記録されていない場合は 80%程度の適当な数値から始めて、再現するまで負荷を高くして行く。 本事例では、再現環境マシンのメモリが 2GByte、スワップが 14GByte で計 16GByte であり、再現せるために約 92%程度のメモリ負荷(16GByte×92%≒23×640MByte) が必要だった。 $ stress -m 23 --vm-bytes 640M --vm-hang --timeout 180s ※--vm-hang は、一度確保したメモリを stress 終了まで解放しない指定 c. /proc/meminfo や top 等により、メモリ使用状況を確認し、負荷が上がるのを待つ d. アプリケーションを起動し、異常終了するのを待つ 上記手順により、障害が再現することを確認する。 2.4.1.4 解析 (1) ltrace による解析 障害が再現できたので、次のステップとして障害箇所の切り分けを行うため、システム コール/ライブラリコールをトレースする。まずライブラリコールトレーサを用い、更に システムコールレベルの詳細な情報が必要な場合にシステムコールトレーサを使う。ライ ブラリコールトレーサ ltrace 経由でアプリケーションを起動して障害を再現する手順は、 以下の通り。 a.~c. 前述の手順と同様 d. ltrace 経由でアプリケーション起動し、異常終了するのを待つ $ ltrace -f -o ltrace.log アプリケーション名 トレース結果を確認する際には、まずエラーを返しているシステム/ライブラリコール に着目して、当たりをつける。また障害箇所が特定できる場合は、そこから遡って見て行 き、障害の原因となるシステム/ライブラリコールを特定できるかどうかを確認する。 - 2-25 - ltraceのトレース結果を、図 2.4-1 に示す。 $ ltrace -f -o ltrace.log mem_app 1. セグメンテーションフォールトで異常終了したことが分かる :(省略) 5421 sleep(1) = 0 5421 malloc(10485760) = 0x927b3008 5421 printf("%u\tmsg-out: %d\n", 59, 10485760) 2. 直前の malloc コールが失敗 し NULL が返っている = 22 5421 sleep(1) = 0 5421 malloc(10485760) = NULL 3. その前の malloc コールは成 功している 5421 --- SIGSEGV (Segmentation fault) --5421 +++ killed by SIGSEGV +++ 図 2.4-1 アプリケーション異常終了時の ltrace 結果 トレース結果の最後にはセグメンテーションフォールトで異常終了したことが出力され ており、その直前に malloc が NULL を返し失敗したことが分かる。しかし、その前の malloc は成功しているため、最後の malloc 付近で障害が発生したことが分かる。 (2) ソースコードの解析 次にアプリケーションのソースコードを入手し、mallocを実行しているコードを確認し た所、図 2.4-2 のように2箇所でmallocを行っている部分が見つかった。 :(省略) 1. malloc 実行箇所その1 p = malloc(SIZE); for (i = 0; i < SIZE; i++) p[i] = 'a'; 2. malloc 実行箇所その2 :(省略) p = malloc(MAX_BUF_SIZE); for (writes = 0; writes < MAX_BUF_SIZE; writes += cnt) { cnt = read(f, buf, size); if (cnt == 0) return 1; else if (cnt < 0) return 0; memcpy(p + writes, buf, cnt); } :(省略) 図 2.4-2 アプリケーションソース(malloc 実行箇所) - 2-26 - どちらの malloc が問題になっているのかを明らかにするため、ライブラリコールの引き数 値や前後のライブラリコールの流れをトレース結果と比較することで、切り分けを行う。 本事例では、引き数が異なっており、SIZE と MAX_BUF_SIZE を確認した所、問題とな っている malloc は前者の方だということが分かった。 前者の malloc 周辺をよく見ると、メモリ確保が失敗した場合でもそのまま NULL ポイン タに書き込みを行ってしまうことが分かる。よって、通常メモリが確保できる状況下では 問題なく動作するが、メモリ高負荷状況ではメモリ確保に失敗し、NULL ポインタ書き込 みによりセグメンテーションフォールトが発生することが分かる。 メモリ確保関数で NULL が返るようなメモリ高負荷状況下では、OOM killer が動作し、 カーネルの算出式によって決定される任意のプロセスが kill されてしまう可能性がある。 そこで稼働環境を確認した所、/proc/sys/vm/overcommit_memory の値は既に 2 に設定され ており、オーバーコミットは禁止されていた(OOM killer は動作しない)ことが分かった。 2.4.1.5 対策 障害原因が処理抜けの場合、他にも同様に処理が抜けている箇所があることが予想され る。よって、ソース全体を検索し同様の箇所がないか全て確認する必要がある。このため、 ソースを検索しメモリ確保(malloc, calloc)を使用している箇所で、返り値チェックが抜 けているものを洗い出し、返り値チェックを追加した。その後、再現させて異常終了しな いことを確認した。 2.4.1.6 付録~再現用アプリケーションのソースコード 本事例を再現させるためのアプリケーション(mem_app)のソースコードは、下記の通 り。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define SIZE (10 * 1024 * 1024) char *write_buf(void) - 2-27 - { int i; char *p; p = malloc(SIZE); for (i = 0; i < SIZE; i++) p[i] = 'a'; return p; } int proc_open() { int f; f = open("/proc/kcore", O_CREAT|O_RDONLY); return f; } int proc_read(int f) { int cnt, writes, size = 128; char *p, buf[size]; if (f < 0) return 0; if (lseek(f, SIZE, SEEK_CUR) < 0) return 0; p = malloc(SIZE); for (writes = 0; writes < SIZE; writes += cnt) { cnt = read(f, buf, size); if (cnt == 0) return 1; else if (cnt < 0) return 0; memcpy(p + writes, buf, cnt); } return 1; } - 2-28 - int main_loop(void) { unsigned int n; char *p; int f = -1; for (n = 0;; n++) { if (n < 4096) p = write_buf(); else if (n == 4096) f = proc_open(); else if (n == 4097) proc_read(f); else if (n == 4098) { if (f >= 0) close(f); } printf("%u\tmalloced: %d\n", n, SIZE); sleep(1); } return 1; } int main(int argc, char *argv[]) { main_loop(); exit(0); } - 2-29 - 2.4.2 高負荷時にアプリケーションが異常終了する障害の解析(コアダンプあ り) 前節(2.4.1)と同じ障害(高負荷時にアプリケーションが異常終了)が発生した際にコ アダンプが取れていた場合、障害解析がどのように異なるかを、以下に報告する。 2.4.2.1 概要 表 2.4-1 を参照のこと。 2.4.2.2 障害情報収集と初期切り分け 本事例ではコアダンプが取れていたため、再現手段の確立を飛ばして、コアダンプ情報 を元にした障害解析作業を行う。 2.4.2.3 解析 (1) gdb による解析 コアダンプが取れていた場合、デバッガ gdb を用いることで、どういった関数呼び出し 順の中のどの関数で障害が発生したか、即座に解析可能である。アプリケーションのコン パイル時に-g オプション付きで gcc でコンパイル済みであれば、更にその関数内のどのス テップで障害が発生したか、関数の引き数値は何だったかまで、解析可能である。 本事例では、アプリケーションは-g オプション付きで gcc でコンパイル済みであった。 gdb での障害箇所特定の手順を以下に示す。 a. gdb を起動し、障害発生関数を確認する $ gdb mem_app core.5421 :(省略) 1. アプリケーション名とコア ファイル名を指定して、gdb を起動 Reading symbols from /lib/tls/libc.so.6...done. Loaded symbols for /lib/tls/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x08048537 in write_buf () at mem_app.c:18 18 p[i] = 'a'; 2. write_buf 関数内で障害発生 したことが分かる 3. -g 付きでコンパイルしていれ ば、更にソースファイル名や 行番号、引き数の値も分かる (これ以降の斜め文字部分) (gdb) b. gdb の where コマンドで、どういった関数呼び出し順の中で障害が発生したかを確認す る (gdb) where #0 0x08048537 in write_buf () at mem_app.c:18 #1 0x08048683 in main_loop () at mem_app.c:60 #2 0x08048721 in main (argc=3, argv=0xbffffa64) at mem_app.c:77 - 2-30 - main → main_loop → write_buf の順で呼び出した際に、 write_buf 関数中で障害発生し たことが分かる c. gdb の l コマンドで、障害発生付近のソースを確認する(-g オプション付き時のみ有効) (gdb) l 13 int i; 14 char *p; gdb 起動時に表示された行番号 の部分に着目する。障害はこの 行で発生している 15 16 p = malloc(SIZE); 17 for (i = 0; i < SIZE; i++) 18 p[i] = 'a'; 19 20 return p; 21 } 22 (gdb) 以上により、gdbによる解析だけで障害発生箇所が特定でき、更にソースまで確認できる。 コアダンプが残っていない前節(2.4.1)での障害解析と比較すると、再現手段の確立~障 害箇所の特定までのステップが、たったこれだけの作業で置換できることが分かる(表 2.4-2 参照)。障害によっては再現が難しい場合も多々あることも考慮すると、障害解析作 業の簡略化のためには、アプリケーションコンパイル時の-gオプションとコアダンプの設定 が重要である。 表 2.4-2 項 事前準備の違いによる障害解析ステップの違い 障害解析ステップ 番 解析難易度 コアダンプ設 コアダンプ設定 コアダンプ設定 定なし時 あり時 と-g オプション あり時 1 再現手段の確立 高 低 低 2 障害箇所の特定 高 中 低 3 障害原因の究明 中 中 中 2.4.2.4 対策 2.4.1.5 を参照のこと。 - 2-31 - 2.4.3 高負荷時にアプリケーションが Out of Memory で強制終了された障害の 解析(コアダンプなし) 通常の負荷だと問題なく動作するアプリケーションが、メモリ高負荷な状況下では強制 終了する障害に関して、解析と対策を以下に報告する。 2.4.3.1 概要 本障害とその対策の概要を 表 2.4-3 に示す。 表 2.4-3 高負荷時アプリケーション異常終了の概要 番号 2.4.3 現象 通常負荷時は問題なく動作するアプリケーションが、Out of Memory 発生日 2005/xx/xx 解決日 2005/xx/xx で強制終了してしまう 分類 アプリケーション強制終了 発生環境 OS MIRACLE LINUX V4.0 beta CPU Xeon 2.0 * 2 メモリ 6GByte ハードディスク SCSI 72GByte ネットワーク Intel 82545EM Gigabit Ethernet 原因 i2o ドライバの不具合 対策 カーネルバージョンアップ 2.4.3.2 障害情報収集と初期切り分け Iozone で高負荷をかけると、Out of memory (OOM) killer が走りアプリケーションが強制 終了されてしまう。 /var/log/messages 等には OOM killer によって強制終了されたプロセスの情報等がある。 エラーメッセージが出力されている場合、その文字列の意味から障害原因が特定できな いかを判断する。また Web 上でエラーメッセージを検索する等して同様な障害報告がない かを確認する。 2.4.3.3 再現手段の確立 まず、現象が再現するかどうかを確認する。再現手順は、以下の通り。 a. Iozone を流し高負荷状態にする。 上記手順により、障害が再現することを確認する。 2.4.3.4 解析 今回の場合は常に再現した。環境を確認してみると i2o ドライバを必要とする場合、当該障 害が発生することがわかった。 - 2-32 - インターネット等(Red Hat の bugzilla および Linux Kernel Mailing List(LKML))で検索 してみると i2o ドライバが 2.6 カーネルで大幅に変更されていることが分かった。LKML で質問したところ、最新版にバージョンアップして再現をすることを薦められた。 そこで、最新版のカーネルで再現実験をおこなったところ、OOM killer による強制終了は 発生しなかった。 2.4.3.5 対策 カーネルのバージョンアップ。 - 2-33 - 2.5 スローダウン 2.5.1 パフォーマンス監視ツールの障害解析 本節では、パフォーマンス監視ツールのスローダウン現象を取り上げ、その概要と再現 手順、主に LKST を用いた障害解析手順を示す。また、最後に本障害解析手法に対する留 意点を述べる。 2.5.1.1 障害の概要 事例として取り上げる障害の概要を以下の 表 2.5-1 に示す。 表 2.5-1 パフォーマンス監視ツール障害の概要 番号 現象 2.5.1 2005/xx/xx 発生日 解決日 2005/xx/xx 高負荷時、sar/iostat/mpstat コマンドによる統計情報取得の時間間隔 が指定した値にならない 分類 スローダウン 発生環境 OS MIRACLE LINUX V4.0 beta CPU Intel Pentium Ⅲ 1.26GHz ×1 メモリ 1GB ハードディスク Ultra3 SCSI ネットワーク Intel Corp. 82544EI Gigabit Ethernet 36GB ×1 Controller 原因 ファイルシステムのコミット待ち プロセス数増加に伴う実行権待ち 対策 出力データを tmpfs 上のファイルに保存する nice コマンドによる優先度の変更 ファイルリダイレクトの利用(sar のみ) 解析手法 カーネル内部トレースによる遅延要因の特定 Linuxシステムにはsar、iostatおよびmpstatという、一定間隔ごとにシステムの統計情 報(CPU利用率、ディスク読込み/書込み量など)を取得するコマンドがある。ただし、高い 負荷を掛けた状態においては、以下の 図 2.5-1 ように統計情報が指定した時間間隔で採取 できないという問題が発生する場合がある。 # sar -A -o sar.dat 5 600 5 秒間隔でデータを取得する # sar -u -f sar.dat Linux 2.6.9-5.25AX (TAMA09) 21:29:47 CPU %user 08/10/05 %nice %system - 2-34 - %iowait %idle 21:29:52 all 0.00 0.00 0.20 0.40 99.40 21:29:57 all 0.00 0.00 0.00 0.60 99.40 21:30:02 all 12.25 0.00 83.73 4.02 0.00 時間間隔が 21:30:16 all 1.00 0.00 40.03 58.97 0.00 指定した 5 秒 21:30:50 all 0.83 0.00 34.29 64.88 0.00 ではない 21:31:08 all 1.12 0.00 46.76 52.12 0.00 21:31:30 all 0.59 0.00 25.23 74.18 0.00 21:31:58 all 1.15 0.00 46.31 52.54 0.00 21:32:17 all 0.61 0.00 49.04 50.35 0.00 21:32:22 all 0.80 0.00 99.20 0.00 0.00 21:32:27 all 1.00 0.00 99.00 0.00 0.00 21:32:32 all 0.60 0.00 99.40 0.00 0.00 21:32:37 all 0.60 0.00 99.40 0.00 0.00 図 2.5-1 パフォーマンス監視ツールの障害発生の様子 2.5.1.2 障害の再現 障害を解析するにあたり、まず同様の障害を再現させる。障害の再現を検証した環境を 表 2.5-2 に示す。 表 2.5-2 障害再現・解析環境 ハードウェア CPU Intel Pentium III 1.26GHz ×1 メモリ 1GB ソフトウェア HDD Ultra3 SCSI OS MIRACLE LINUX V4.0 beta LKST 2.3-3AX (rpm からインストール) sysstat 36GB ×1 5.0.5-1.1AX(ディストリビューションに付属して いる rpm からインストール) IOzone 3.239(ソースからインストール) Stress 0.18.2-1.rf(ソース RPM からインストール) 障害を再現する際、一般的には障害が発生したときと同じシステム構成/負荷状況で再 現させることが理想的だが、この障害は発覚時のシステム構成が不明であること、および 各種のアプリケーションで高負荷状態が発生したときに発生していることから、典型的な 高負荷状況を擬似的に生成し、障害再現を確認する。 本節で想定した負荷状況と使用した負荷生成ツールを以下の 表 2.5-3 に示す。 - 2-35 - 表 2.5-3 想定した負荷状況と負荷生成ツール 負荷状況 負荷生成ツール 詳細 “-c (プロセス数)”オプションで実行 CPU 負荷 (平方根の計算を繰り返す) Stress “-m 1 –vm-bytes (malloc メモリサイズ)”オプ メモリ負荷 ションで実行 (malloc/free の実行を繰り返す) “-CMR -i0 -+n -+u -s 500M ディスク I/O 負荷 IOzone -t 1 -f io1”オプシ ョンで実行 (ディスクへの書込み/読み込み) 障害解析をおこなうスローダウン事例としては以下の 表 2.5-4 の 2 つのケースを取り上 げる。 表 2.5-4 障害現象の再現確認 測定ツール 負荷状況 ケース 1 sar ディスク I/O 負荷 ケース 2 iostat CPU 負荷 具体的な障害の再現確認手順を以下に述べる。上の 表 2.5-4 の各ケースに対して、以下 の手順でシステム統計情報を取得し、障害の再現確認を行う。 (1) パフォーマンス監視ツールによるモニタリング開始 (2) (1)から 10 秒後に負荷生成の開始 (3) (2)の負荷生成の終了から 10 秒後にモニタリング終了 (4) (1)から (3)の間に取得したモニタリングデータの確認 今回の測定では以上の (1)から (3)の手順を自動化したスクリプトを用いた。このスクリプ トを 図 2.5-2 に示す。 #!/bin/bash if [ $# != 3 ]; then echo "Usage: ./load.sh <load_type> <nr of worker> <mon_type>" >& 2 exit 1 fi load_type=$1 worker=$2 mon_type=$3 - 2-36 - export LANG=C DATE_ID=`date +%y%m%d_%H%M%S` SAVE_DIR=${load_type}_${worker}_${mon_type}_${DATE_ID} INTERVAL=5 COUNT=600 TIMEOUT=240 LOG_FILE=load.log mkdir ${SAVE_DIR} echo "Make Directory ${SAVE_DIR}" | tee -a ${LOG_FILE} # Start Monitoring (1) echo "Monitoring Start at `date`" | tee -a ${LOG_FILE} モニタリングの if [ ${mon_type} = sar ]; then 開始 sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} & elif [ ${mon_type} = iostat ]; then iostat –t -x ${INTERVAL} ${COUNT} > ${SAVE_DIR}/iostat.dat & else mpstat -P ALL ${INTERVAL} ${COUNT} > ${SAVE_DIR}/mpstat.dat & fi sleep 10 # Start Load echo "Load Start at `date`" | tee -a ${LOG_FILE} (2) if [ ${load_type} = cpu ]; then 負荷生成 stress -c ${worker} -t ${TIMEOUT} elif [ ${load_type} = mem ]; then stress -m ${worker} -t ${TIMEOUT} else iozone_wrap ${worker} 500 fi echo "Load Finish at `date`" | tee -a ${LOG_FILE} sleep 10 (3) # Stop Monitoring モニタリングの if [ ${mon_type} = sar ]; then 終了 killall sar - 2-37 - killall sadc elif [ ${mon_type} = iostat ]; then killall iostat else killall mpstat fi echo "Monitoring Finish at `date`" | tee -a ${LOG_FILE} 図 2.5-2 障害再現に利用したスクリプト(load.sh) また、load.shの中で使用している、IOzoneを呼出すスクリプトiozone_wrapを以下の 図 2.5-3 に示す。 #!/bin/bash if [ $# != 2 ]; then echo "Usage: ./iozone_wrap <worker> <file_size>" >&2 exit 1 fi worker=$1 file_size=$2 TMP_DIR=~/tmp num=0 while [ $num -lt ${worker} ] do iozone -CMR -i0 -+n -+u -s ${file_size}M -t 1 \ -f ${TMP_DIR}/io${num} > /dev/null & num=`expr ${num} + 1` done wait 図 2.5-3 iozone を呼出すスクリプト iozone_wrap 以下に、load.shスクリプトの内部処理の流れを 図 2.5-4 に示す。 - 2-38 - (1)モニタリング開始 第3引数で与えられたコマンドを利用 (5秒間隔で600回データを取得) 10秒後 (2)負荷生成 第1引数で与えられた負荷タイプを 第2引数で与えられた負荷量で実行 ・第1引数がcpuの場合は第2引数の数だけ平方根計算プロセスを起動 ・第1引数がmemの場合は(第2引数)MBのメモリのmalloc/freeを繰返す ・第1引数がioの場合(第2引数)個のプロセスが500MBのファイルを書込む 10秒後 (3)モニタリング終了 (1)で開始したモニタリングを終了 図 2.5-4 load.sh の内部処理 以下の 表 2.5-5 にload.shが受け取る引数の仕様を示す。 表 2.5-5 load.sh の引数 引数 第1引数 説明 cpu/mem/io のいずれかを指定する cpu : stress -c による CPU 負荷を発生させる mem : stress -m によるメモリ負荷を発生させる io : iozone によるディスク I/O 負荷を発生させる 第2引数 負荷を発生させるプロセスの数を指定する 第3引数 sar/iostat/mpstat を指定する sar : sar でモニタリングする iostat : iostat でモニタリングする Mpstat : mpstat でモニタリングする 以下の 表 2.5-6 にload.shが生成する出力ファイルについて説明する(これらのファイル は、load.shの実行ディレクトリに作成される)。 表 2.5-6 load.sh の出力ファイル 出力ファイル名 概要 (第 1 引数)_(第 2 引数)_(第 3 引数)_(実行時刻)/ パフォーマンス監視ツール(第 3 引数で指 (第 3 引数).dat 定)が取得したデータが保存される。 - 2-39 - モニタリングツールのデータ保存ディレク トリ、モニタリングツールの開始/終了時 刻、および負荷生成の開始/終了時刻が このファイルに追記される load.log ((実行時刻)には load.sh スクリプトを実行開始した時刻が(西暦2桁)(月2桁)(日2桁)_(時2 桁)(分2桁)(秒2桁)の形式で入る) 以上に示したスクリプトを用いて、再現確認を行う。 ■ケース 1:ディスク I/O 高負荷時における sar のスローダウン事例の再現確認 まず、ディスク I/O 高負荷状態で sar の障害を再現させるために以下のコマンドで実行し、 統計情報を取得する。 # load.sh io 2 sar モニタリング開始時刻 Make Directory io_2_sar_050913_103530 負荷生成開始時刻 Monitoring Start at Tue Sep 13 10:35:30 JST 2005 Load Start at Tue Sep 13 10:35:40 JST 2005 負荷生成終了時刻 Load Finish at Tue Sep 13 10:36:11 JST 2005 /root/bin/load.sh: line 57: 7007 Terminated sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} モニタリング終了時刻 Monitoring Finish at Tue Sep 13 10:36:21 JST 2005 図 2.5-5 ケース1の再現確認 上述の手順で取得したデータを以下の手順で確認する。 # cd io_2_sar_050913_103530/ # sar -u -f sar.dat Linux 2.6.9-5.25AX (TAMA09) 09/13/05 10:35:30 CPU %user %nice %system %iowait %idle 10:35:35 all 0.20 0.00 0.00 0.60 99.20 10:35:40 all 0.20 0.00 0.00 0.40 99.40 10:35:45 all 2.40 0.00 97.41 0.20 0.00 10:36:08 all 0.47 0.00 16.39 65.89 17.25 10:36:13 all 0.00 0.00 6.20 3.60 90.20 10:36:18 all 0.20 0.00 0.00 0.40 99.40 Average: all 0.54 0.00 18.66 32.25 48.56 23 秒開いて いる 図 2.5-6 ディスク I/O 高負荷時の sar の取得データ ディスクに負荷をかけている間(10:35:40 から 10:36:11)の期間にデータ取得タイミング が 23 秒と大きく遅延する様子が再現できている。よって、ディスク I/O 高負荷の環境で障 - 2-40 - 害が再現できた。 ■ケース 2:CPU 高負荷時における iostat のスローダウン事例の再現確認 次に、CPU 高負荷状態において iostat の障害を再現させるために、以下のコマンドを実 行し、統計情報を取得する。 # load.sh cpu 1000 iostat Make Directory cpu_1000_iostat_050917_142852 Monitoring Start at Sat Sep 17 14:28:52 JST 2005 Load Start at Sat Sep 17 14:29:02 JST 2005 stress: info: [4100] dispatching hogs: 1000 cpu, 0 io, 0 vm, 0 hdd stress: info: [4100] successful run completed in 240s Load Finish at Sat Sep 17 14:33:02 JST 2005 /root/bin/load.sh: line 57: 4095 Terminated iostat –t -x ${INTERVAL} ${COUNT} >${SAVE_DIR}/iostat.dat Monitoring Finish at Sat Sep 17 14:33:12 JST 2005 図 2.5-7 ケース2の再現確認 上述の手順で取得したデータを以下の手順で確認する。 # cd cpu_1000_iostat_050917_142852 # grep Time iostat.dat Time: 14:28:52 時刻情報だけを抽出 Time: 14:28:57 Time: 14:29:02 11 秒または 6 秒の開きが発生 Time: 14:29:13 Time: 14:29:19 Time: 14:29:25 Time: 14:29:31 Time: 14:29:36 Time: 14:29:41 Time: 14:29:46 Time: 14:29:51 Time: 14:29:56 Time: 14:30:01 Time: 14:30:06 Time: 14:33:07 Time: 14:33:12 図 2.5-8 CPU 高負荷時の iostat のデータ取得タイミング 以上から、14:29:02 から 14:29:31 までの期間でデータ取得タイミングが指定した 5 秒に - 2-41 - ならない様子が再現できている。よって、CPU 高負荷の環境で障害が再現できた。 2.5.1.3 障害原因候補の洗い出し 障害の原因を解析するために、原因として考えられる現象およびそれらを洗い出す手順 を以下に示す。 本節で対象とする監視ツールはいずれも、一定時間間隔ごとに起動し処理(統計情報の取 得、ファイルへの書き出しなど)を行う「タイマ駆動型アプリケーション」である。タイマ 駆動型アプリケーションの Linux 内部での動きは以下のようになる。 (1) CPU 毎に定期的に発生するローカルタイマ割り込みがハードウェア割り込み ハンドラを起動し、更にハードウェア割り込みハンドラがソフト割り込み要求 を発生させる (2) ソフトウェア割り込みハンドラの中でタイマリスト処理を実行し起動時刻に達 したタイマのハンドラを呼び出す。ここで、Linux にはいくつかのタイマリス トが存在するが、ある実時間が経過した際にプロセスを起床させるためには、 it_real_fn というタイマリストが利用される。it_real_fn は指定した時刻になる と起床すべきプロセスに対して通知のシグナル(SIGALRM)を生成する (3) タイマをセットしたプロセスはシグナル SIGALRM を受け取ると実行可能状 態(TASK_RUNNING)となりランキューに接続される (4) スケジューラがそのプロセスに実行権を与えると、そのプロセスのシグナルハ ンドラが起動される 上記の流れおよび処理内容(ファイルI/Oが発生すること)に基づいて、障害の原因として 考えられる箇所および原因内容を 表 2.5-7 に示す。 表 2.5-7 原因箇所の候補と原因内容 項番 1 原因箇所 ハードウェア割込み 原因内容 ローカルタイマのハードウェア割込みの発生に対 して、H/W 割込みハンドラの実行が遅延する H/W 割込みハンドラによるソフトウェア割込み要 2 ソフトウェア割込み 求に対して、ソフトウェア割込みハンドラ実行が遅 延する 指定時刻になると実行されるプロセスはタイマリ 3 タイマリスト処理の起動 ストで管理され、指定時刻になるとプロセスに起床 するようにシグナルを送るが、指定時刻と比較し、 この処理が遅延する タイマリスト処理中にプロセスへのシグナル 4 タイマリスト処理 SIGALRM の送信が遅延する - 2-42 - シグナルの送信に対して、プロセスの起床(実行 5 シグナル処理の遅延 可能状態への遷移)が遅延する プロセスが実行可能状態になってから、実行権を取 6 CPU 待ちの遅延 得するまでに他のプロセスが優先されるなどの理 由で、プロセスの実行が遅延する 大量の計算を行うなどのためにプロセスの処理が 7 実行時間の遅延 8 入出力処理による遅延 予定時間内に終了せず遅延する 統計情報の読み込みおよびファイルへの出力処理 が長くかかり遅延する 以上の遅延とイベントの関連を 図 2.5-9 に示す。 イベント 時間軸 ローカルタイマ H/W 割込み発生 ローカルタイマ ハンドラ実行 タイマリスト処理実行 タイマリスト ハンドラ 起動指定時刻 S/W 割込み発生 S/W 割込み 1 H/W 割込み 2 S/W 割込み 3 ハンドラ 4 SIGALRM 送信 繰返し 5 SIGALRM 受信 実行可能状態へ遷移 6 対象 プロセス 実行状態へ遷移 7 入出力開始 8 入出力終了 図 2.5-9 遅延とイベントの関連 上で洗い出した原因候補に対して効率的に解析を進めるために、原因の可能性を考慮し - 2-43 - 解析の解析順位をつける。 ■ケース 1(ディスク I/O 高負荷時における sar のスローダウン事例)の場合 sarの挙動がスローダウンする現象は、ディスクI/O高負荷状況で発生しているので 表 2.5-7 の項番 8 の入出力処理に関する遅延が最も疑わしく、これを解析順位1番とする。つ づいて、iozoneプロセスが優先されて実行される可能性を考え項番 6 のCPU待ちの遅延、 その他は必要に応じて処理の流れをさかのぼって解析を進めることとする。 ■ケース 2(CPU 高負荷時における iostat のスローダウン事例)の場合 iostatの挙動がスローダウンする現象は、CPU高負荷時に発生しているため、表 2.5-7 の 項番 6 のCPU待ちの遅延が一番原因の可能性が高いと考えられ、これを解析順位 1 番とす る。 2.5.1.4 LKST による障害解析手順 2.5.1.3 節で洗い出した障害の原因候補について調査するためには、図 2.5-9 に示したカー ネル内部の 1 から 8 に関する各イベントを取得/解析できる必要がある。今回の障害解析に おいてはその要求を満たすツールとしてカーネルトレースツールLKST(Linux Kernel State Tracer)を使用する。以下にLKSTを使用して解析するための手順を示す。 (1) LKST モジュールロード LKST を起動するにはカーネルモジュール lkst をロードする必要がある。また、プロセ ス の 状 態 遷 移 や ウ ェ イ ト キ ュ ー の 詳 細 な 状 況 を 取 得 す る た め に lksteh_procstat や lksteh_wqcounter などの LKST 拡張モジュールもロードする。 本障害解析では、測定前に LKST を初期化するために、始めにモジュールのアンロード /ロードを行っている。 # modprobe -r lksteh_wqcounter # modprobe -r lksteh_vminfo # modprobe -r lksteh_sysinfo # modprobe -r lksteh_procstat # modprobe -r lksteh_fsinfo # modprobe -r lkst # modprobe lkst # modprobe lksteh_fsinfo # modprobe lksteh_procstat # modprobe lksteh_sysinfo # modprobe lksteh_vminfo # modprobe lksteh_wqcounter 図 2.5-10 LKST モジュールのロード (2) マスクセットファイルの作成 - 2-44 - LKST では記録するカーネルイベントを選択するためにマスクセットを利用するが、マス クセットの内容はファイルに保存して必要なときに再設定できる。マスクセットファイル はシステムコールやソフトウェア割込みなどの解析対象(アナライザ)に応じて用意する必 要があり、エディタで編集することも可能だが、lkst_make_mask コマンドを利用して簡 単に作成することができる。以下に、lkst_make_mask コマンドの利用方法を示す。 # lkst_make_mask (マスクセット名) (アナライザ1) (アナライザ2) … # lkstm read –n (マスクセット名) > (マスクセットファイル) 図 2.5-11 マスクセットファイルの作成方法 本障害解析で作成したマスクセットとアナライザの対応関係を以下の 表 2.5-8 に示す。 表 2.5-8 マスクセットファイルと対応アナライザ マスクセット ファイル名 対応アナライザ maskset_irq timer syscall procstat softirq runqueue schedrun waitcpu maskset_wq schedule schedrun syscall waitqueue waittime (3) マスクセットの設定 LKSTでは複数のマスクセットを登録しておき、それらのマスクセットを切り替えること で、取得するカーネルイベントを変更することができる。以下に (2)で作成したマスクセッ トファイルを設定する方法を示す。 # lkstm write -m 4 -n test_mask write -f maskset_file マスクセットファイル(maskset_file)を元に マスクセット ID=4、マスクセット名=test_mask というマスクセットを登録する (マスクセット ID は 3 から 254 までの値が使える) # lkstm set -n test_mask 上で登録したマスクセット”test_mask”を有効にする(この時点で test_mask に 設定されたイベントが記録され始める) 図 2.5-12 マスクセットの設定 (4) バッファの準備 LKST は取得したイベントをまずメモリ上のバッファに記録しておき、LKST による記録 が終了した後にデータをファイルに保存し、解析に利用することを前提としている。デフ ォルトでは利用可能なバッファが 64KB 用意されるが、取得するイベントの量が多くて 64KB では足らない場合、さらに大きなサイズ(最大 64MB)のバッファを用意し、利用する ことができる。それでも不足する場合は複数のバッファを切り替えて利用することができ る。本節では IOzone が大量のブロック I/O リクエストを発行するため、以下の手順により - 2-45 - IA-32 プラットフォームにおいて LKST で使用できるバッファの最大サイズである 100MB のバッファを確保する。 # lkstbuf create -s 1M -b 254 # lkstbuf jump -b 254 # lkstbuf delete -b 0 # lkstbuf create -s 64M -b 1 -n 2 # lkstbuf create -s 35M -b 2 -n 1 # lkstbuf jump -b 1 # lkstbuf delete -b 254 図 2.5-13 バッファの準備 (5) モニタリング開始 パフォーマンス監視ツールを起動して、5 秒間隔でシステム統計情報を取得する。以下の 手順により output_file というファイルにデータを保存する。 # sar –A –o output_file 5 600 ケース1の場合 # iostat –t -x 5 600 > output_file ケース2の場合 図 2.5-14 パフォーマンス監視ツール起動 (6) 負荷の生成 ディスク I/O 負荷を発生させる場合は IOzone を用いて 2 つのプロセスがそれぞれ 500MB のファイルを書き込む負荷を生成させる。CPU 負荷を発生させる場合は stress を 用いて、1000 個のプロセスが平方根を 50 秒間計算する負荷を発生させる。 # iozone_wrap 2 500 ケース1の場合 # stress –c 1000 –t 50 ケース2の場合 図 2.5-15 負荷の生成 (7) LKST によるイベント取得の停止 以下の手順で LKST によるイベント取得を停止する。 # lkst stop 図 2.5-16 LKST によるイベント取得の停止 (8) モニタリング終了 以下の手順でパフォーマンス監視ツールを停止する。 # killall sar ケース1の場合 # killall sadc - 2-46 - ケース2の場合 # killall iostat 図 2.5-17 パフォーマンス監視ツールの停止 (9) LKST が記録したデータのファイルへの保存 LKST によるイベント取得を停止した時点ではイベントはメモリ上に記録されたままな ので、lkstbuf コマンドを用いてファイルに保存する。また、CPU が複数存在するマシン上 でデータを取得した際は lkstlogdiv コマンドを利用してログを分割する必要がある(CPU が 1基の場合は必須ではないが、手順の汎用性を考えこの処理を行う)。 このあとは、生成された lkstlog-0 から必要な情報を引き出して障害解析を行うことにな る。 # lkst stop lkstlog-0, lkstlog-1 とログファイルが CPU の数だけ # lkstbuf read –f lkstlog できる(今回は CPU は 1 基なので 1 つのファイル # lkstlogdiv lkstlog lkstlog-0 が生成される) 図 2.5-18 イベント取得の停止と取得イベントのファイルへの保存 本節の解析では以上の手順を自動化した 図 2.5-19、図 2.5-20 のスクリプトを用い、障 害解析を行った(ただし、(2)の マスクセットファイルの作成はスクリプト実行前に行ってお くものとする)。 #!/bin/bash # Arguments check if [ $# != 1 ]; then echo "Usage: start_i.sh <maskset_file>" >& 2 exit 1 fi MASKSET_NAME=test_mask MASKSET_FILE=$1 LKST_LOG_FILE=lkstlog LOG_FILE=lkst.log INTERVAL=5 COUNT=600 SAVE_DIR=lkst-`date +%Y%m%d_%H%M%S` echo "Make Directory ${SAVE_DIR}" | tee -a ${LOG_FILE} mkdir ${SAVE_DIR} - 2-47 - # lkst restart modprobe -r lksteh_wqcounter modprobe -r lksteh_vminfo (1) modprobe -r lksteh_sysinfo LKST モジュールロード modprobe -r lksteh_procstat modprobe -r lksteh_fsinfo modprobe -r lkst modprobe lkst modprobe lksteh_fsinfo modprobe lksteh_procstat modprobe lksteh_sysinfo modprobe lksteh_vminfo modprobe lksteh_wqcounter (3) #/etc/init.d/lkst start マスクセットの設定 # Write maskset id = 4 lkstm write -m 4 -n ${MASKSET_NAME} write -f ${MASKSET_FILE} # Change mask lkstm set -n ${MASKSET_NAME} # Minimum lkst buffer size lkstbuf create -s 1M -b 254 lkstbuf jump -b 254 lkstbuf delete -b 0 (4) バッファの準備 # Get memory for recording lkstbuf create -s 64M -b 1 -n 2 lkstbuf create -s 35M -b 2 -n 1 lkstbuf jump -b 1 (5) lkstbuf delete -b 254 モニタリングの開始 # Start sysstat #mon_sar 5 100 & echo "Monitoring Start at `date`" | tee -a ${LOG_FILE} sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} & sleep 30 # Generate Load - 2-48 - echo "Load Start at `date`" | tee -a ${LOG_FILE} (6) iozone_wrap 2 500 負荷の生成 echo "Load Finish at `date`" | tee -a ${LOG_FILE} sleep 10 (7) # Stop event recording LKST によるトレースの終了 lkst stop # Stop sar (8) killall sar モニタリングの終了 killall sadc echo "Monitoring Finish at `date`" | tee -a ${LOG_FILE} lkstbuf read -f ${SAVE_DIR}/${LKST_LOG_FILE} cd ${SAVE_DIR} lkstlogdiv ${LKST_LOG_FILE} 図 2.5-19 ケース 1 の測定スクリプト start_i.sh #!/bin/bash # Arguments check if [ $# != 1 ]; then echo "Usage: start_m.sh <maskset_file>" >& 2 exit 1 fi MASKSET_NAME=test_mask MASKSET_FILE=$1 LKST_LOG_FILE=lkstlog LOG_FILE=lkst.log INTERVAL=5 COUNT=600 SAVE_DIR=lkst-`date +%Y%m%d_%H%M%S` echo "Make Directory ${SAVE_DIR}" | tee -a ${LOG_FILE} mkdir ${SAVE_DIR} - 2-49 - # lkst restart modprobe -r lksteh_wqcounter (1) modprobe -r lksteh_vminfo LKST モジュールロード modprobe -r lksteh_sysinfo modprobe -r lksteh_procstat modprobe -r lksteh_fsinfo modprobe -r lkst modprobe lkst modprobe lksteh_fsinfo modprobe lksteh_procstat modprobe lksteh_sysinfo modprobe lksteh_vminfo modprobe lksteh_wqcounter (3) #/etc/init.d/lkst start マスクセットの設定 # Write maskset id = 4 lkstm write -m 4 -n ${MASKSET_NAME} write -f ${MASKSET_FILE} # Change mask lkstm set -n ${MASKSET_NAME} # Minimum lkst buffer size lkstbuf create -s 1M -b 254 lkstbuf jump -b 254 (4) lkstbuf delete -b 0 バッファの準備 # Get memory for recording lkstbuf create -s 64M -b 1 -n 2 lkstbuf create -s 35M -b 2 -n 1 lkstbuf jump -b 1 lkstbuf delete -b 254 (5) # Start sysstat モニタリングの開始 #mon_sar 5 100 & echo "Monitoring Start at `date`" | tee -a ${LOG_FILE} iostat –t -x ${INTERVAL} ${COUNT} > ${SAVE_DIR}/iostat & sleep 30 # Generate Load echo "Load Start at `date`" | tee -a ${LOG_FILE} - 2-50 - stress -c 1000 -t 50 (6) echo "Load Finish at `date`" | tee -a ${LOG_FILE} 負荷の生成 sleep 10 # Stop event recording (7) lkst stop LKST によるトレースの終了 # Stop sar (8) killall iostat echo "Monitoring Finish at `date`" | tee -a ${LOG_FILE} モニタリングの終了 lkstbuf read -f ${SAVE_DIR}/${LKST_LOG_FILE} cd ${SAVE_DIR} lkstlogdiv ${LKST_LOG_FILE} 図 2.5-20 ケース 2 の測定スクリプト start_c.sh 図 2.5-21 にstart_i.shスクリプトの内部処理の流れを示す。 - 2-51 - (1)LKTモジュールロード 一旦すべてのモジュールをアンロードした後にロードする (3)マスクセットファイルの設定 第1引数として指定されたファイルを マスクセットファイルとして設定する (4)バッファの準備 100MBのサイズの保存用バッファを用意する (5)モニタリング開始 sar を用い5秒間隔で100回データを取得する 30秒後 (6)負荷生成 iozone2プロセスで500MBのファイル書込みを行う 10秒後 (7)LKSTによるトレース停止 (8)モニタリング終了 (9)LKSTトレースのファイルへの保存 図 2.5-21 start_i.sh の内部処理 以下の 表 2.5-9 に、start_i.shが受け取る引数の仕様を示す。 表 2.5-9 start_i.sh の引数 引数 第1引数 説明 LKST イベント取得に利用するマスクセットファイルを指定する 以下の 表 2.5-10 にstart_i.shスクリプトが出力するファイルを示す(これらのファイルは start_i.shの実行ディレクトリに作成される)。 表 2.5-10 start_i.sh の出力ファイル 出力ファイル名 概要 lkst-(実行時刻)/sar.dat トレース中に取得した sar のデータが保存される lkst-(実行時刻)lkstlog-0 LKST で取得したイベントがバイナリ形式で保存される - 2-52 - データ保存ディレクトリと モニタリングの開始/終了時刻、 負荷生成の開始/終了時刻が保存される lkst.log ((実行時刻)に start_ish スクリプトを実行開始した時刻が(西暦2桁)(月2桁)(日2桁)_(時2 桁)(分2桁)(秒2桁)の形式で入る) 以下に start_i.sh の利用手順を示す。 # ./start_i.sh maskset_wq Make Directory lkst-20050915_120817 New maskset id=4 was written. (Name:test_mask) Currently selected maskset was changed to id=4 New buffer was created, cpu=0, id=254 size=1048576 + 4032(margin) Currently selected buffer changed to 254 on CPU 0 Buffer id=0 was deleted. New buffer was created, cpu=0, id=1 size=67108864 + 4032(margin) New buffer was created, cpu=0, id=2 size=36700160 + 4032(margin) Currently selected buffer changed to 1 on CPU 0 Buffer id=254 was deleted. Monitoring Start at Thu Sep 15 12:08:18 JST 2005 Load Start at Thu Sep 15 12:08:48 JST 2005 Load Finish at Thu Sep 15 12:09:18 JST 2005 Stop LKST event tracing. ./start_i.sh: line 70: 9124 Terminated sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} Monitoring Finish at Thu Sep 15 12:09:28 JST 2005 # cd lkst-20050915_120817/ # ls lkstlog lkstlog-0 sar.dat 図 2.5-22 start_i.sh の利用手順 start_c.sh については、start_i.sh で IOzone によるディスク I/O 負荷の代わりに 1000 プロセスによる 50 秒間の CPU 負荷を発生させ、sar でモニタリングする代わりに iostat でモニタリングを行い、その結果を lkst-(実行時刻)/iostat.dat に保存している。それ以外は、 start_c.sh と start_i.sh の挙動に違いはないので、start_c.sh の仕様記述は省略する。 2.5.1.5 障害解析(ケース 1) 本節ではケース 1 の障害解析手順および結果について説明する。 ■ケース 1:ディスク I/O 高負荷時における sar スローダウン事例の障害解析 - 2-53 - まず、2.5.1.3 節で洗い出した障害の原因候補について、優先順位の高い順から解析を行 う。 (1) 入出力処理の挙動に関する確認 まず、入出力処理に関する挙動を調べるために、LKST で入出力システムコールの情報や ウェイトキュー、プロセスの状態に関する情報を取得する必要がある(ウェイトキューはプ ロセスの待機理由を詳細に調べるために必要)。そのため、以下の手順でマスクセットファ イルを作成し、それを用いてイベントを取得する。 # lkst_make_mask maskset_3 procstat schedule schedrun syscall waitqueue waittime # lkstm read -n maskset_3 > maskset_wq # ./start_i.sh maskset_wq Make Directory lkst-20050917_160707 New maskset id=4 was written. (Name:test_mask) Currently selected maskset was changed to id=4 New buffer was created, cpu=0, id=254 size=1048576 + 4032(margin) Currently selected buffer changed to 254 on CPU 0 Buffer id=0 was deleted. New buffer was created, cpu=0, id=1 size=67108864 + 4032(margin) New buffer was created, cpu=0, id=2 size=36700160 + 4032(margin) Currently selected buffer changed to 1 on CPU 0 Buffer id=254 was deleted. Monitoring Start at Sat Sep 17 16:07:08 JST 2005 Load Start at Sat Sep 17 16:07:38 JST 2005 Load Finish at Sat Sep 17 16:08:09 JST 2005 Stop LKST event tracing. ./start_i.sh: line 70: 6111 Terminated sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} Monitoring Finish at Sat Sep 17 16:08:19 JST 2005 図 2.5-23 マスクセットファイルの作成と LKST トレースの実行 測定後、まずこの測定で障害が発生していることを確認する。 # cd lkst-20050917_160707/ # sar -u -f sar.dat Linux 2.6.9-5.25AX (TAMA09) 09/17/05 16:07:08 CPU %user %nice %system %iowait %idle 16:07:13 all 1.20 0.00 1.59 0.60 96.61 16:07:18 all 0.40 0.00 0.20 0.40 99.00 16:07:23 all 0.00 0.00 0.00 0.20 99.80 16:07:28 all 0.20 0.00 0.00 0.60 99.20 - 2-54 - 16:07:33 all 0.20 0.00 0.00 0.40 99.40 16:07:38 all 0.20 0.00 0.40 0.60 98.80 16:07:43 all 2.20 0.00 97.80 0.00 0.00 16:08:06 all 0.54 0.00 35.20 48.02 16.24 16:08:11 all 0.20 0.00 8.02 5.01 86.77 16:08:16 all 0.20 0.00 0.00 0.40 99.40 Average: all 0.54 0.00 20.06 17.27 62.14 23 秒開く 図 2.5-24 sar スローダウンの確認 この結果から、16:07:43 から 16:08:06 の間でデータ取得タイミングが 23 秒開く様子が 観察でき、障害が再現できていることが確認できる。 a. 入出力システムコールとプロセスの状態の解析 まず、sadc プロセス(sar のバックエンドプロセスで実際に統計情報の取得やファイルへ の保存を行う)が発行する入出力に関するシステムコール(read, write, fsync, fdatasync な ど)の実行で遅延が発生していないかを以下の手順で確認する。 # lkstla procstat -s lkstlog-0 | grep sadc 6113 3213.000000000 sadc 480 6.693750000 8.000000000 5.000000000 2.675 sadc の PID6113 であることが分かる # lkstla syscall -s –p6113 lkstlog-0 > syscall_sadc.stat 図 2.5-25 システムコール統計情報の取得 上のコマンドで得られた結果を以下のコマンドでグラフ化する。 # lkst_plot_stat syscall_sadc.stat 図 2.5-26 システムコール統計情報のグラフ化 すると、図 2.5-27 が得られ、fdatasync(ディスクI/Oにおいてメモリ上のデータをディス ク上のデータと同期させるシステムコール)の列のmaxの値を確認すると、約 19 秒という非 常に長い遅延が発生していることが確認できる。 - 2-55 - 約 19 秒近く 遅延している 図 2.5-27 sadc プロセスのシステムコールの回数と処理時間の統計 次に、システムコール fdatasync がどのタイミングで遅延しているかを調べるために、シ ステムコール呼出しと処理時間の時系列データを確認する。この情報を得るために以下の コマンドを実行する # grep fdatasync syscall_sadc.stat 148 19.843863369 fdatasync 28.781 11 1.803987579 18.924932028 0.019923120 fdatasync のシステムコール番号が 148 であることが分かる # lkstla syscall -l -p6113 -k148 lkstlog-0 System call analyzer sysno syscall_name 6113 は sadc の PID、148 は fdatasync のシステムコール番号 start[sec] processing-time 148 fdatasync 1126940828.017242039 0.030491725 148 fdatasync 1126940833.022834720 0.034036871 148 fdatasync 1126940838.021166238 0.019923120 148 fdatasync 1126940843.020340621 0.022785987 148 fdatasync 1126940848.019599594 0.025715150 148 fdatasync 1126940853.018784141 0.028568158 148 fdatasync 1126940858.024250161 0.684125676 148 fdatasync 1126940863.023344847 18.924932028 148 fdatasync 1126940886.948701006 0.022870817 - 2-56 - 148 fdatasync 1126940891.947976012 0.029745859 148 fdatasync 1126940896.947143087 0.020667978 図 2.5-28 fdatasync 処理状況の時系列データの取得 上の 図 2.5-28 からfdatasyncの処理が遅延している時刻が分かるが、その前後のsadcプ ロセスの状態(実行中または待機中など)を知るために以下のコマンドを実行する。 # lkstla procstat -l –p6113 lkstlog-0 Process status analyzer pid task_name start[sec] process-stat 6113 sadc 1126940863.052936460 8.000000000 6113 sadc 1126940863.052943369 5.000000000 6113 sadc 1126940868.021156294 7.000000000 6113 sadc 1126940881.829223874 7.000000000 6113 sadc 1126940881.948244364 8.000000000 (略) 16:07:43 16:08:01 (略) 図 2.5-29 sadc プロセスの状態遷移情報の取得 この結果、図 2.5-29 のデータが得られ、これと 図 2.5-28 を比較すると、fdatasyncが呼 び出された直後に状態 5(TASK_UNINTERRUPTIBLE:割込み不可状態で待機する状態)に 遷移し、途中で状態 7(TASK_RUNNING:実行可能状態)に遷移していることが分かる。 b. ウェイトキュー関連の解析 次に、なぜシステムコール fdatasync の処理で遅延するかを調べるために、sadc プロセ スがどこで、ウェイトキューにつながれているかを以下の手順で確認する。 Linux においてはディスクへの書込み完了やタイムアウト待ちなどのようにプロセスが ある事象を待つ場合、カーネルがそのプロセスをウェイトキューに登録して管理する。よ って、ウェイトキューを調べることでどのような事象でプロセスが待機しているかを明ら かにすることができる。 以下のコマンドで、ウェイトキューにプロセスを登録するイベントを取得し、その中か ら時刻 16:07:43.052943369 付近で sadc をウェイトキューにつないでいるイベント (pid=00006113 になっているイベント)を探す。 # lkstbuf print -r -E lkst_etypes -e "waitqueue counting" -f lkstlog-0 (略) event_type=waitqueue counting cpu=00, pid=00006113 time=Sat Sep 17 16:07:43.052942274 2005 arg1=0xc18edaa4 00000000 : pointer to wait_queue_head arg2=0xf6a7a700 00000000 : pointer to added process - 2-57 - arg3=0xf8863799 00000000 : pointer to call address arg4=0x00000000 00000000 : waitqueue length (略) 図 2.5-30 ウェイトキューにプロセスをつなぐイベントの確認 取得したイベントの arg3 の値は sadc プロセスをウェイトキューにつないだ関数のアド レスを表す。その具体的な関数名は、以下のコマンドで確認することができる。 # lkstla waitqueue –s –k 0xf8863799 lkstlog-0 waitqueue length analyzer address min calling_point count average max log_wait_commit+138 27 0.037037037 1.000000000 total percent f8863799 0.000000000 1.000000000 100.00 図 2.5-31 sadc プロセスをウェイトキューにつないでいる関数の確認 上の結果において calling_point の列を見ることにより、log_wait_commit という関数の 内部で sadc プロセスをウェイトキューにつないでいることが分かる。この関数はファイル システムにおけるジャーナリング処理のコミットの完了を待つ関数なので、sadc プロセス はコミットの完了を待つために状態 5 に遷移したことが分かる。 次に sadc プロセスが状態 7 に遷移しているタイミングで、どのプロセスが sadc プロセ スを起床させているかを確認する。以下のコマンドで、プロセスを起床しているイベント を抽出し、sadc プロセスが状態 7 に遷移しているタイミング(16:08:01.829223874)付近を 調べる(起床したプロセスは arg1 から判断できる)。 # lkstbuf print -r -E lkst_etypes -e "wakeup_pid" -f lkstlog-0 (略) event_type=wakeup_pid cpu=00, pid=00000706 time=Sat Sep 17 16:08:01.829223874 2005 arg1=0x000017e1 00000000 : wakeup pid arg2=0x00000003 00000000 : process state 0x17e1 は sadc の PID の arg3=0x00000000 00000000 : synchronus 16 進表示 (略) 図 2.5-32 プロセスの起床イベントの確認 該当イベントの pid の項目を見ると、PID が 706 のプロセスが sadc プロセスを起床させ ていることが分かる。このプロセスの名前は以下のコマンドで確認できる。 :# lkstla procstat -s -p706 lkstlog-0 Process status analyzer pid task_name count average - 2-58 - max min total percent 706 kjournald 220 6.804545455 8.000000000 5.000000000 1497.000000000 100.000 図 2.5-33 sadc プロセスを起床させているプロセスの確認 以上より kjournald プロセスが sadc プロセスを起床させていることが分かる。よって、 fdatasync システムコールの処理が遅延している理由は、kjournald プロセスが行うジャー ナル処理におけるコミットの完了を sadc プロセスが待っているためと考えられる。 (2) CPU 待ち遅延の確認 入出力処理の次に考えられる遅延の要因として、CPU 待ちの有無を調査する。sadc プロ セスの状態遷移に関する情報を取得して CPU 待ちが発生していないかを確認する。 # lkstla procstat -l lkstlog-0 > procstat.log # lkst_plot_log procstat.log 6113 図 2.5-34 sadc プロセスの状態遷移に関する情報の取得 実行状態 ディスク I/O 負荷発生中 実行可能状態 シグナル受付可能待機状態 シグナル受付不可待機状態 図 2.5-35 sadc の状態遷移 - 2-59 - 上図でプロセスがどの状態で待機しているかは分かるが、プロセスの状態遷移の細かい 挙動が分かりづらいので、テキストデータを確認する(図 2.5-35 の 35 秒から 55 秒付近を 抽出している)。 # cat procstat_sadc.log (略) 6113 sadc 1126940863.052833438 8.000000000 6113 sadc 1126940863.052838322 5.000000000 6113 sadc 1126940863.052928263 7.000000000 6113 sadc 1126940863.052936460 8.000000000 6113 sadc 1126940863.052943369 5.000000000 6113 sadc 1126940868.021156294 7.000000000 6113 sadc 1126940881.829223874 7.000000000 6113 sadc 1126940881.948244364 8.000000000 5 秒状態 5 で待機 14 秒状態 7 で待機 (略) 図 2.5-36 sadc プロセスの詳細な状態遷移 この結果、sadcプロセスは状態 5 と状態 7 で長い間待機していることが分かる。状態7 での長時間の待ちについては、2.5.1.7 節で考察する。 (3) タイマ処理の挙動の確認 まず以下の手順でソフトウェア割込み、タイマリスト、スケジューリングおよびプロセ ス状態遷移などのイベントを取得するマスクセットを作成し(入出力に関する調査をした際 にこれらのイベントも同時に取得すると LKST バッファがあふれるため 2 回に分けて測定 している)、作成したマスクセットを利用して、LKST で前述したイベントをトレースする。 # lkst_make_mask maskset_1 timer syscall procstat softirq runqueue schedrun waitcpu # lkstm read -n maskset_1 > maskset_irq # ./start_i.sh maskset_irq Make Directory lkst-20050917_164451 New maskset id=4 was written. (Name:test_mask) Currently selected maskset was changed to id=4 New buffer was created, cpu=0, id=254 size=1048576 + 4032(margin) Currently selected buffer changed to 254 on CPU 0 Buffer id=0 was deleted. New buffer was created, cpu=0, id=1 size=67108864 + 4032(margin) New buffer was created, cpu=0, id=2 size=36700160 + 4032(margin) Currently selected buffer changed to 1 on CPU 0 Buffer id=254 was deleted. Monitoring Start at Sat Sep 17 16:44:52 JST 2005 Load Start at Sat Sep 17 16:45:22 JST 2005 - 2-60 - Load Finish at Sat Sep 17 16:45:56 JST 2005 Stop LKST event tracing. ./start_i.sh: line 70: 7940 Terminated sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} Monitoring Finish at Sat Sep 17 16:46:06 JST 2005 図 2.5-37 マスクセットファイルの作成とトレースの実行 今回の測定においても sar がスローダウンしているかどうかを以下の手順で確認する。 # cd lkst-20050917_164451 # sar -u -f sar.dat Linux 2.6.9-5.25AX (TAMA09) 09/17/05 16:44:52 CPU %user %nice %system %iowait %idle 16:44:57 all 1.40 0.00 1.40 0.60 96.61 16:45:02 all 9.98 0.00 1.00 1.00 88.02 16:45:07 all 0.20 0.00 0.00 0.40 99.40 16:45:12 all 0.00 0.00 0.00 0.60 99.40 16:45:17 all 0.20 0.00 0.00 0.40 99.40 16:45:22 all 0.20 0.00 0.40 0.40 99.00 16:45:27 all 1.80 0.00 98.20 0.00 0.00 16:45:32 all 1.00 0.00 99.00 0.00 0.00 16:45:42 all 0.99 0.00 99.01 0.00 0.00 16:45:53 all 0.29 0.00 25.36 41.01 33.33 16:45:58 all 0.20 0.00 6.00 4.60 89.20 16:46:03 all 0.00 0.00 0.00 0.80 99.20 Average: all 1.25 0.00 32.50 6.62 59.63 11 秒開いている 図 2.5-38 sar スローダウンの確認 図 2.5-38 よりsarがスローダウンしていることが確認できる。以降はこのトレースで得ら れたLKSTデータに対して解析を行う。 まず以下の手順でタイマリスト処理の起動遅延に関する統計データを取得する。 # lkstla timer –s lkstlog-0 > timer.stat 図 2.5-39 タイマリスト処理に関するデータの取得 以上の手順で得られた結果を以下の手順でグラフ化すると 図 2.5-41 のようになる。 # lkst_plot_stat timer.stat 1 timerdelayanalyzer.pdf - 2-61 - 図 2.5-40 タイマリスト処理に関するデータのグラフ化 最大遅延は 0.2ms 以下 図 2.5-41 タイマリスト処理の回数とタイマリスト起動遅延時間 2.5.1.3 節の (2)で述べたように、sadcプロセスは指定した時刻に起床するためにit_real_fn というタイマリストを用いている。そのため、ここではit_real_fnを重点的にチェックする。 図 2.5-41 においてit_real_fnタイマリストのmaxの値を確認すると 1 回のタイマリストの 起動遅延は最大でも 0.2ms以下であることから、タイマリスト処理の遅延もsarスローダウ ンの原因でないことが分かる。 (4) タイマソフトウェア割込みの挙動の確認 まず、以下の手順でソフトウェア割込みの発生から割込みハンドラ実行までの遅延の統 計データを取得する。 # lkstla softirq –s lkstlog-0 > softirq.stat 図 2.5-42 ソフトウェア割込みに関するデータの取得 以上の手順で得られた結果を以下の手順でグラフ化すると 図 2.5-44 のようになる。 # lkst_plot_stat softirq.stat 1 software-irqdelayedtimeanalyzer.pdf - 2-62 - 図 2.5-43 ソフトウェア割込みに関するデータのグラフ化 最大遅延が 0.4ms 以下 図 2.5-44 ソフトウェア割込みの回数と遅延時間 図 2.5-44 においてtimerのmaxの値を調べると、定期的(MIRACLE LINUX V4.0 betaでは 1ms毎)に発生するtimerソフトウェア割込みは、1回の処理で 0.4ms以上遅れていない。よ って、timerソフトウェア割込みの遅延がsarスローダウンの原因ではないと考えられる。 (5) スケジューリング処理に関する確認 次に、ランキューの長さとスケジューリング処理の遅延の関係を以下のコマンドで取得 する。 - 2-63 - # lkstla schedrun -s lkstlog-0 1 回のスケジューリング scheduler overhead per runqueue-len analyzer 処理の最大遅延 len runqueue count average max min total percent 1 rq-1 0.000949479 2 1876 0.000000506 0.000003607 0.000000274 0.000001290 0.000009732 0.000000292 0.000001447 0.000006825 0.000000284 878 0.000001241 0.000005424 0.000000300 241 0.000000867 0.000003632 0.000000330 32 0.000001217 0.000003314 0.000000336 31 0.000001524 0.000003160 0.000000370 29 0.000001172 0.000003073 0.000000303 23 0.000001176 0.000002498 0.000000373 17 0.000001423 0.000002795 0.000000376 9 0.000001675 0.000002723 0.000000508 2 0.000001585 0.000002443 0.000000727 10.931 rq-2 1010 スケジューリング 0.001302848 14.999 処理の遅延合計 3 rq-3 3419 0.004945749 4 rq-4 0.001089553 5 6 7 0.448 rq-7 0.000047244 8 0.544 rq-8 0.000033982 9 0.391 rq-9 0.000027039 0.311 rq-10 0.000024194 0.279 rq-11 0.000015071 12 2.407 rq-6 0.000038944 11 12.543 rq-5 0.000209055 10 56.937 0.174 rq-12 0.000003170 0.036 図 2.5-45 ランキューの長さとスケジューリング処理の遅延の確認 得られた結果の max の値から1回のスケジューリング処理では 0.1ms 以上の遅延は認め らない。また、トレース中におけるスケジューリングの合計処理時間も total の値を合計し て求めると、0.008686328 秒となり、sar による遅延(11 秒)に比べるとはるかに小さい。よ ってスケジューリング処理による遅延が原因とは考えがたい。 ■ケース 1 のまとめ 以上、LKST を用いた障害の原因追究を行い、ジャーナリング処理におけるコミットの完 - 2-64 - 了待ちという結果を得ることができた。この障害を回避する方法としては、sar の出力先に tmpfs を使用するなどが考えられる。具体的な回避策とのその効果については 3.1.5.4 節を 参照のこと。 以下の 表 2.5-11 に、ケース 1 における障害解析結果の概要をまとめる。 表 2.5-11 ディスク I/O 高負荷時の sar のスローダウンに関する解析結果 原因候補 遅延 遅延の詳細 (8) 入出力処理 あり fdatasync システムコールが 20s 遅延している箇所あり (6) CPU 待ちの遅延 注意 (4) タイマリスト処理 なし 最大遅延は 0.2ms 以下 (2) ソフトウェア割込み なし 最大遅延は 0.4ms 以下 (6) スケジューリング処理 なし 合計でも 9ms 程度 状態 5(割込み不可状態で待機)と状態 7(実行可能状態)で 合計して 15s 待機している箇所あり。内容吟味必要。 2.5.1.6 障害解析(ケース 2) 本節ではケース 2 の障害解析手順・結果について説明する。 ■ケース 2:CPU 高負荷時における iostat スローダウン事例の障害解析 まず、2.5.1.3 節で洗い出した障害の原因候補について、原因の可能性が一番高いと思わ れるCPU待ちについて調べるためにプロセスの状態遷移を測定する。 最初にマスクセットを以下の手順で作成し、それを用いて測定を行う。 # lkst_make_mask maskset_5 procstat schedule schedrun syscall # lkstm read –n maskset_5 > maskset_cpu # ./start_c.sh maskset_cpu Make Directory lkst-20050917_085746 New maskset id=4 was written. (Name:test_mask) Currently selected maskset was changed to id=4 New buffer was created, cpu=0, id=254 size=1048576 + 4032(margin) Currently selected buffer changed to 254 on CPU 0 Buffer id=0 was deleted. New buffer was created, cpu=0, id=1 size=67108864 + 4032(margin) New buffer was created, cpu=0, id=2 size=36700160 + 4032(margin) Currently selected buffer changed to 1 on CPU 0 Buffer id=254 was deleted. Monitoring Start at Sat Sep 17 08:57:47 JST 2005 Load Start at Sat Sep 17 08:58:17 JST 2005 - 2-65 - stress: info: [16251] dispatching hogs: 1000 cpu, 0 io, 0 vm, 0 hdd stress: info: [16251] successful run completed in 50s Load Finish at Sat Sep 17 08:59:07 JST 2005 stress による負荷生成 Stop LKST event tracing. プロセス数は 1000 Monitoring Finish at Sat Sep 17 08:59:17 JST 2005 ./start_c.sh: line 73: 16190 Terminated iostat –t -x ${INTERVAL} ${COUNT} >${SAVE_DIR}/iostat 図 2.5-46 マスクセットファイルの作成と LKST トレースの実行 本測定でも障害が発生していることを確認する。 # cd lkst-20050917_085746: # grep Time iostat.dat Time: 08:57:47 Time: 08:57:52 Time: 08:57:57 Time: 08:58:02 Time: 08:58:07 Time: 08:58:12 スローダウン発生 Time: 08:58:17 (5 秒間隔ではない) Time: 08:58:28 Time: 08:58:34 Time: 08:58:40 Time: 08:58:46 Time: 08:58:51 Time: 08:58:56 Time: 08:59:01 Time: 08:59:06 Time: 08:59:11 Time: 08:59:16 図 2.5-47 iostat のデータ取得タイミングの確認 図 2.5-47 から 08:58:17 から 08:58:46 の期間で 11 秒から 6 秒のiostatのスローダウンが発 生していることがわかる。 (1) CPU 待ち遅延の確認 次に、iostat プロセスの状態遷移を得るために以下のコマンドを実行する。 # lkstla procstat -s lkstlog-0 | grep iostat 16190 377.000000000 iostat 54 6.981481481 0.156 8.000000000 5.000000000 iostat の PID が 16190 と分かる - 2-66 - # lkstla procstat -l lkstlog-0 > procstat.log # lkst_plot_log procstat.log 16190 図 2.5-48 iostat の状態遷移の取得とグラフ化 図 2.5-48 の操作により以下のグラフが得られる。 実行状態 CPU 負荷発生中 実行可能状態 シグナル受付可能待ち シグナル受付不可待ち 図 2.5-49 iostat の状態遷移(負荷プロセス数 1000) 図 2.5-49 からCPU負荷が発生している期間において、タイマのシグナルにより状態 6(シ グナル受付可能状態で待機)から状態 7(実行可能状態)に移り、次の状態 8(実行状態)に移る までに状態 7(実行可能状態)で秒単位の遅延が発生していることがわかる。よって、iostat プロセスはCPU待ち状態でスローダウンしていることが分かる。 (2) 負荷量と遅延の関係 図 2.5-50、図 2.5-51 にCPU負荷を発生しているプロセス数をそれぞれ 500 及び 100 に減 らした場合の状態遷移図を示す(グラフの作成方法は 図 2.5-48 と同じ)。負荷プロセス数が 減ると状態 7 での遅延が軽減されている(start_c.shの”stress –c 1000 –t 50”の行をそれぞ れ”stress –c 500 –t 50”、”stress –c 100 –t 50”に書き換えたスクリプトを使用して測定を行 った)。 - 2-67 - CPU 負荷発生中 実行可能状態 シグナル受付可能待ち 図 2.5-50 iostat の状態遷移(負荷プロセス数 500) 実行可能状態 CPU 負荷発生中 シグナル受付可能待ち 図 2.5-51 iostat の状態遷移(負荷プロセス数 100) - 2-68 - (3) ランキューの長さと優先度の変化 負荷プロセスとiostatプロセスの実行スケジューリングがiostatの遅延に関係しているた め、LKSTによりランキューの長さの変化を確認する(操作コマンドは 図 2.5-53 参照)。図 2.5-52 で示されるように負荷発生中は、1000 個の負荷プロセスは全てランキューにつなが れており、実行スケジューリングに対し長い順番待ちが発生している。 CPU 負荷発生中 図 2.5-52 ランキューの長さの時間変化(負荷プロセス数 1000) # lkstla runqueue -l lkstlog-0 > runqueue.log # lkst_plot_log runqueue.log 0 図 2.5-53 LKST によるランキューの長さ計測 CPU負荷発生中における優先度別のプロセス数の時間変化を以下の 図 2.5-55 に示すス クリプトで計測すると、図 2.5-54 のようになる。カーネルでは起動直後のプロセスには比 較的高い優先度が割当てられるため、本測定の負荷プロセスでは起動直後は優先度として - 2-69 - 76 が割当てられ、後半では 77 に優先度が下がっている。これは状態遷移図(図 2.5-49) において負荷生成直後に状態 7 での遅延が特に大きく、負荷発生期間の前半で遅延が観測 されることと対応している。 1200 合計 : 4 CPU 負荷発生中 1000 プ ロ 優先度 800 600 77 セ ス 78 85 84 83 82 81 80 79 78 77 76 75 400 76 数 200 9:31:41 9:31:42 9:31:44 9:31:45 9:31:46 9:31:47 9:31:48 9:31:50 9:31:51 9:31:52 9:31:53 9:31:54 9:31:56 9:31:57 9:31:58 9:31:59 9:32:00 9:32:01 9:32:03 9:32:04 9:32:05 9:32:06 9:32:07 9:32:09 9:32:10 9:32:11 9:32:12 9:32:13 9:32:15 9:32:16 9:32:17 9:32:18 9:32:19 9:32:20 9:32:22 9:32:23 9:32:24 9:32:25 9:32:26 9:32:28 9:32:29 9:32:30 9:32:31 9:32:32 9:32:34 9:32:35 9:32:36 9:32:37 9:32:38 9:32:40 9:32:41 0 9:31:41 時刻 図 2.5-54 優先度別プロセス数の変化(負荷プロセス数 1000) #!/bin/bash SAVE_DIR=ps-`date +%Y%m%d_%H%M%S` 注意:ディスク I/O の影響を mkdir ${SAVE_DIR} 受けないように tmpfs 上に 出力する while [ 1 ] do ps -elf > ${SAVE_DIR}/`date +%H_%M_%S` sleep 1 done 図 2.5-55 優先度の計測スクリプト ■ケース 2 のまとめ 以上の結果より、CPU 高負荷状態における iostat の遅延は、CPU の実行スケジューリ ング待ちにより発生している。このような CPU 待ちによる遅延を回避するには nice コマ ンドを用いた優先度(NICE 値)の変更などが考えられる。実際に NICE 値を変更した際の挙 動については 3.1.5.4 節を参照されたい。 - 2-70 - 低 高 2.5.1.7 障害解析手順についての留意点 本節では、sar と iostat を例にとりタイマ駆動型アプリケーションの遅延障害の解析手法 を紹介した。同様の解析をおこなう上での留意点を以下に述べる。 ■主要因の絞込み タイマ駆動型アプリケーションでは、表 2.5-7 に示す複数の遅れ要因があるが、遅れ時 間の大きさにより、疑わしい要因がある程度絞り込まれる。本節の例では 10 秒以上の遅れ が発生しているため、最も応答時間の遅いディスク入出力にかかわる周辺から調査を進め た。しかし、これが 1msオーダーの遅れを問題とする解析では、最初に調査すべき要因も 変わってくることに留意されたい。 ■長時間の状態7での待ち ケース 1 のsarの遅延解析では、ジャーナル処理のコミット待ちが遅延原因であった。図 2.5-35、図 2.5-36 では一度状態 5(シグナル受付不可待機状態)で 5 秒待った後、状態7(実 行可能状態)に遷移しここでも 14 秒待ちに入っている。状態7になっているためプロセス はランキューに接続されているが、状態 8(実行状態)になる前なのでウェイトキューにも 接続されている状態で待ちになっている。待ちの解除は、kjournaldプロセスがジャーナル 処理のコミットを完了したこと(図 2.5-32)により、もう一度状態 7 に遷移し直ちに状態 8 となってウェイトキューから外されるという順序(図 2.5-36)なので、状態7の長時間 の待ちも、実態はジャーナル処理のコミット待ちであり、ケース 2 のようなプロセスの実 行スケジューリングを待っているわけではない。LKSTにより状態 7 から状態 7 への遷移が 観測された場合には、このような待ち原因の吟味が必要である。 ■LKST による解析 LKST の利用は、ソフト割込みやタイマリスト、システムコールの解析手順のよう に、”lkstla (アナライザ名) -s (logfile)”というコマンドで、簡単にさまざまなイベントの遅 延に関する統計情報が取得・グラフ化が容易であり、障害の要因を絞り込むのに非常に有 用である。 ただし、統計情報により要因概要(本節では fdatasync システムコールの処理が遅延して いる)が判明しても、さらに深い原因追求を行う場合は、LKST で取得したイベントから関 連しそうなものを抽出し、そこから付随する情報を引き出す必要がある(本節ではウェイト キューにつなぐイベントやプロセスを起床させるイベントを抽出し、プロセスをウェイト キューにつなぐ関数やプロセスを起床させるプロセスを調べた)。LKST をより効果的に利 用するためには、これらの手順の再利用/自動化などの機能拡張がなされると、更に利用し やすいツールとなる。 - 2-71 - ■LKST の記録時間 LKST がイベントを記録するバッファサイズの上限が 100MB に限られる点は、記録時間 に関する注意が必要である。計測中 LKST がイベント記録用のバッファを使い切っていな いことを確認するために、以下のコマンドでバッファの利用状況を監視する方法が有効で ある。 # lkstbuf ls id cpu 255 0 size prev_id next_id readp writep wrap 32768 NUL NUL 0 0 0 1 0* 67112896 2 2 55717440 55717504 0 2 0 1 1 4032 4032 0 36704192 図 2.5-56 バッファの利用状況の確認 LKST のイベントを取得していくと writep の数値が増えていく。この値がバッファのサ イズを超えないことを確認する必要がある。もし超えてしまう場合は、取得するイベント の種類を減らしたり、負荷量(発生するイベントの量)を調整したりする必要がある。 取得すべきイベントを減らせない場合には、測定を複数回に分けて行うなどの工夫が必 要となる。また、再現性が低い障害や測定しなければいけない期間が非常に長い障害など の場合も、バッファを使い切ってしまうことがないように工夫する、または計測したい事 象が記録されたらバッファがその後のイベントにより上書きされる前に計測を停止するな どの工夫が必要である。 - 2-72 - 2.5.2 システムコールトレーサがトレース対象プロセスを遅延させる障害の解 析 高負荷な状況下で sar を実行すると、取得しているデータが欠落するという問題が報告さ れている。この障害をシステムコールトレーサである strace および lkst を用いて解析した 所、strace が sar プロセスを遅延させてしまう別な問題があることが分かった。この障害 に関して、解析と対策を以下に報告する。 2.5.2.1 概要 本障害とその対策の概要を 表 2.5-12 に示す。 表 2.5-12 高負荷時 strace 問題の概要 番号 2.5.2 現象 高負荷時、strace がトレース対象プロセスの処理を遅延させてしまう 分類 スローダウン 発生環境 OS Fedora Core 3 CPU Xeon 2.4GHz×1 メモリ 2GByte ハードディスク IDE 120GByte ネットワーク Intel 82545EM Gigabit Ethernet Controller 発生日 2005/xx/xx 解決日 2005/xx/xx 原因 strace ログ出力が他のファイル I/O 待ちにより遅延する 対策 strace ログ出力を ramfs 上のファイルに対して出力する(改善策) 解析手法 lkst による解析(所要時間が長いシステムコールを確認~事象待ち要 因の解析~事象待ち根本原因の追跡~I/O キュー、WAIT キューからの 解析結果裏付け) 2.5.2.2 障害発生の経緯 sar の高負荷時データ欠落問題を解析するため、まず障害解析環境で再現することを確認 する。その際の手順を以下に示す。 a. sar を1秒間隔で実行 $ sar 1 0 b. 高負荷状況作成ツール stress によって、メモリ負荷が高い状況を再現する $ stress -m 100 --vm-bytes 32M --vm-hang --timeout 180s ※stress の設定は環境により異なる。ここでは、物理メモリ(2GByte)の約 1.5 倍(1.5 ×2GByte≒100×32MByte)を設定。 c. sar の出力が欠落することを確認して、関連プロセス(stress と sar)を kill する - 2-73 - この手順により、stress 実行直後に sar の出力間隔が不安定になり、データが欠落すること を確認した。 スローダウン障害の場合、悪影響を及ぼしているプロセスが存在する可能性がある。こ れを切り分けるため、top コマンドで負荷が高くなっているプロセスがないかを確認する。 本事例では、top で確認したが stress が表示されるだけで、他に CPU/メモリ使用率が問 題になるようなプロセスは存在しなかった。 次に sar で処理時間の長いシステムコールは何かを切り分けるため、システムコールトレ ーサ strace によってトレースを行う。この場合、時間関係のトレース情報が必要であるた め、システムコール処理時間とタイムスタンプを出力するオプション(-ttt と-T)を指定す る。この際の手順を以下に示す。 a. strace 経由で sar を1秒間隔で実行。システムコールのトレースを行う $ strace -f -F -ttt -T -o strace.log sar 1 0 b.~c. 前述の手順と同様 スローダウン障害時のシステムコールログを確認する場合は、処理時間の長いシステム コールに着目する。また、周期的な処理の実装の一つでは、タイマ(alarm システムコー ルによるシグナル SIGALRM の通知)を使用している。本事例のように時刻周期が遅れる ような場合には、alarm システムコール周りにも着目する。 alarmコールを検索しながらタイムスタンプを確認し、1秒毎になっていない箇所を確認 した(図 2.5-57 参照)。 6732 1120049624.827897 alarm(1) = 0 <0.000011> シグナル通知(1秒後)を 設定してから... :(省略) 6730 1120049624.834089 read(0, <unfinished ...> 6732 1120049626.535412 <... pause resumed> ) = ? ERESTARTNOHAND (To be restarted) シグナル受信まで、設定した 1秒ではなく、約2秒かかっ 1120049626.535487 --- SIGALRM (Alarm clock) @ 0 (0) --- ている <1.702452> 6732 図 2.5-57 sar データ欠落時の strace 結果 図 2.5-57 からは、確かに周期が遅れていることが分かるが、 それ以上のことは分からない。 同様に処理時間の長いシステムコールも確認したが、障害箇所を特定することはできなか った。 システムコールトレース結果を確認しても障害箇所が特定できない場合、カーネル状態 トレーサ lkst を用いて、他プロセスの処理を含むカーネル内部動作をトレースし、障害箇 所を特定する。lkst を用いた解析手順を以下に示す。 - 2-74 - a. lkst のモジュールをロードする(以下、スーパーユーザで行う必要あり) # modprobe lksteh_procstat # modprobe lksteh_wqcounter b. lkst のマスクセットを設定する スローダウンの場合、スケジューリング、I/O 待ち等が疑わしいため、これらに該当す るアナライザと、システムコール用のアナライザを設定する # lkst_make_mask debug_mask blkqueue biotime busywait procstat schedule schedrun \ syscall waitqueue waittime # lkstm set -n debug_mask c. lkst のバッファを確保/設定し、一旦バッファを空読みし、クリアする # lkstbuf create -s 63M # lkstbuf jump -b 1 # lkstbuf read -f /dev/null d. 前述の手順により、strace で sar データ欠落をトレースする e. lkst のバッファをファイルに出力する # lkstbuf read -f lkst.log f. lkst ログ解析に使用する lkst イベントタイプをファイルに保存する # cp /proc/lkst_etypes lkst_etypes lkstログの解析を行うため、最初に関連プロセスであるstrace、 sar、 sadcのプロセス 番号を確認する。プロセス番号の確認手順を 図 2.5-58 に示す。 $ lkstla procstat -s lkst.log | grep 8591 strace 1. プロセス一覧から strace をフィルタし... strace 26996 7.195510446 8.00000000 194250.00000000 5.00000000 2. pid を確認 図 2.5-58 lkst ログからの pid 確認(strace の例) 同様にsar、 sadcのプロセス番号も確認した所、各プロセスの関係とpid値は、図 2.5-59 のようになっていた。 親 strace pid: 8591 図 2.5-59 子 sar pid: 8592 sadc pid: 8594 sadc は、/proc 下か ら情報を取得する プロセス sar データ欠落障害時のプロセス関係と pid - 2-75 - 次にsarのalarmシステムコール周期が遅れている部分を確認する(図 2.5-60 参照)。 $ lkstla syscall -l -p 8594 System call analyzer sysno syscall_name :(省略) -k 27 lkst.log 1. sadc プロセス(pid: 8594)が発行 したシステムコールからシステム コール番号 27(alarm)をフィル タして時刻順に表示する ※alarm システムコール番号が分か start[sec] processing-time らない場合は、以下のコマンドで システムコール一覧を表示する $ lkstla syscall -s lkst.log 27 alarm 1122005643.014185632 0.000030569 27 alarm 1122005644.014663423 0.000029989 27 alarm 1122005645.401448302 0.000029725 27 alarm 1122005650.286725212 0.000029849 27 alarm 1122005651.286560847 0.000029863 2. 発行周期が 1 秒でない部分を確認 27 alarm 1122005652.287015489 0.000030419 図 2.5-60 sar データ欠落時障害時の alarm コール発行状況(lkst ログの抜粋) 図 2.5-60 より、障害は時刻 1122005645~1122005650 の周辺で発生していることが分か る。 次に、sarの問題かどうかを切り分けるため、障害発生時刻付近のプロセス状態を確認す る(図 2.5-61 参照)。この結果、sadcがalarmコールから約1秒後にスケジューリングされ た直後にstraceに制御が移り、そのままstraceが割り込み不可状態で事象待ちとなり、約3 秒が経過していることが分かった。よって問題はsarではなく、straceの処理が遅延してい ることにあると考えられる。 $ lkstla procstat -lP -p8591,8592,8594 lkst.log strace, sar, sadc プロセスの状態の変化を時刻順に表示 Process status analyzer pid task_name pid start[sec] :(省略) process-stat alarm コールから約1秒経過 8594 sadc 8594 1122005646.402007570 7.000000000 8594 sadc 8594 1122005646.402011642 8.000000000 8591 strace 8591 1122005646.402017460 7.000000000 8594 sadc 8594 1122005646.402018826 3.000000000 8591 strace 8591 1122005646.402018919 8.000000000 8591 strace 8591 1122005646.402072318 5.000000000 8591 strace 8591 1122005649.268903292 7.000000000 8591 strace 8591 1122005649.927424669 8.000000000 8591 strace 8591 1122005649.928668505 5.000000000 8591 strace 8591 1122005649.928681947 7.000000000 - 2-76 - sadc はスケジューリン グ直後にトレース状態 (状態 3)で待ちになっ ている その直後、strace に制御 が移り、割り込み不可状 態で事象待ち(状態 5) になったまま、3秒近く 経過している 8591 strace 8591 1122005650.286440488 8.000000000 8594 sadc 8594 1122005650.286468765 7.000000000 図 2.5-61 sar データ欠落障害時のプロセス状態(lkst ログの抜粋) 更にlkstログより、この時刻付近のシステムコールを解析した所、straceのwriteシステム コールで遅延していることが分かった(図 2.5-62 参照)。 $ lkstla syscall -lP -p8591,8592,8594 lkst.log strace, sar, sadc プロセスの syscall 発行を時刻順に表示 System call analyzer sysno syscall_name pid start[sec] processing-time :(省略) 29 pause 8594 1122005645.966796426 0.435217434 114 wait4 8591 1122005645.968398497 0.433625642 78 gettimeofday 8591 1122005646.402032753 0.000003976 26 ptrace 8591 1122005646.402037847 0.000002775 26 ptrace 8591 1122005646.402041041 0.000000756 78 gettimeofday 8591 1122005646.402051381 0.000003075 write 8591 1122005646.402062455 3.884396753 4 26 ptrace 8591 1122005650.286464671 0.000004680 114 wait4 8591 1122005650.286470737 0.000069908 78 gettimeofday 8591 1122005650.286548666 0.000004072 図 2.5-62 alarm コールから 約1秒経過 strace の write システム コ ー ル が 約 4秒 か か っ ていることが分かる sar データ欠落障害時のシステムコール(lkst ログの抜粋) 当初は sar データ欠落障害を追跡していたのだが、その途中で strace にも高負荷状況下 での使用に関しては問題があることが判明した(当初追跡していた、sar データ欠落障害の 解析と対策に関しては、2.5.1 節を参照)。 2.5.2.3 解析 (1) lkst による解析(所要時間が長いシステムコールを確認) straceのシステムコールで他にも長時間(10msec以上)掛かっているものが存在するか 。 どうかを確認する(図 2.5-63 参照) $ lkstla syscall -lP -p8591 -m0.01:100 lkst.log | grep -v wait4 strace システムコールを処理時間でフィルタ する。また、wait4 はトレース対象プロセスの イベント待ちなので、それも除く System call analyzer sysno syscall_name 4 write pid start[sec] processing-time 8591 1122005618.357494243 - 2-77 - 0.015721569 4 write 8591 1122005628.987744834 0.361722669 26 ptrace 8591 1122005629.350419772 0.412785495 26 ptrace 8591 1122005645.402513623 0.558999814 write 8591 1122005646.402062455 3.884396753 4 3 read 8591 1122005653.287346371 0.012485473 3 read 8591 1122005654.302765216 0.013471801 図 2.5-63 strace で 10msec 以上掛かったシステムコールの一覧 これらのシステムコールの内、一番長時間掛かっているwrite(時刻 1122005646 秒の時 のもの)に関して解析を行った。このwriteコールは前述の 図 2.5-62 と同じ箇所であり、 割り込み不可状態での事象待ちに長時間掛かっていることまでは 図 2.5-61 で解析済みで ある。 (2) lkst による解析(事象待ち要因の解析) 次のステップとして、何の事象を待っているのかを確認することで、障害要因箇所を追 跡する。カーネル 2.6 では、事象待ちとなる際に、事象毎に WAIT キューにつなぐ処理を 行う。 lkstではこのイベント(waitqueue counting)をトレースでき、そのイベント引き数を確 認することで、どの関数内からWAITキューにつないだかを確認することができる。lkstロ グ解析による事象待ち関数の特定を 図 2.5-64 に示す。 $ lkstbuf print -r -E lkst_etypes -e "waitqueue counting" -f lkst.log :(省略) 1. WAIT キューにつなぐイベントのみ表示 event_type=waitqueue counting 2. 時刻からイベントを特定 strace の pid と時刻からイベントを 特定 cpu=00, pid=00008591 time=Fri Jul 22 13:14:06.402071375 2005 arg1=0xf7f82464 00000000 : pointer to wait_queue_head arg2=0xf7c1c230 00000000 : pointer to added process arg3=0xc01f8d1f 00000000 : pointer to call address 3. WAIT キューにつなぐアドレスを チェック arg4=0x00000001 00000000 : waitqueue length $ lkstla waitqueue -s -k 0xc01f8d1f 4. waitqueue イベントの一覧からチェック したアドレスをフィルタ lkst.log waitqueue length analyzer address min c01f8d1f 0.000000000 calling_point count average max start_this_handle+593 2 0.500000000 1.000000000 total 5. この関数内から WAIT キューにつな ぐ処理を行っていることが判明 1.000000000 図 2.5-64 lkst ログ解析による strace 事象待ち関数の特定 - 2-78 - この結果、start_this_handle 関数内で WAIT キューにつながれていることが分かる。 次に該当関数ソース内のどのステップでWAITキューにつないでいるかを特定する。 objdumpコマンドによりカーネルを逆アセンブラし、周辺の関数コールなどから判断する ことにより特定する(図 2.5-65、図 2.5-66 参照)。 $ objdump -d --start-address=0xc01f8d1f vmlinux WAIT キューにつなぐアドレスを指定 Disassembly of section .text: c01f8d1f <start_this_handle+0x593>: 付近に printk, schedule コールが c01f8d1f: 81 7e 14 3c 4b 24 1d cmpl あることを確認 $0x1d244b3c,0x14(%esi) c01f8d26: 74 23 je c01f8d4b <start_this_handle+0x5bf> c01f8d3f: c7 04 24 c8 ac 39 c0 movl $0xc039acc8,(%esp) c01f8d46: e8 27 30 f3 ff call c012bd72 <printk> c01f8d4b: 8b 46 18 mov 0x18(%esi),%eax c01f8d74: 0f 85 b0 03 00 00 jne c01f912a <start_this_handle+0x99e> c01f8d7a: e8 01 31 19 00 call c038be80 <schedule> c01f8d7f: 89 da mov %ebx,%edx :(省略) :(省略) 図 2.5-65 WAIT キュー接続位置のカーネル逆アセンブラ static int start_this_handle(journal_t *journal, handle_t *handle) { transaction_t *transaction; :(省略) /* * If the current transaction is locked down for commit, wait for the * lock to be released. */ if (transaction->t_state == T_LOCKED) { DEFINE_WAIT(wait); start_this_handle 関数内で schedule をコールしているのは2箇所(そのう ちの1箇所目) prepare_to_wait(&journal->j_wait_transaction_locked, &wait, TASK_UNINTERRUPTIBLE); spin_unlock(&journal->j_state_lock); schedule(); - 2-79 - このステップで WAIT キューにつなぐ と思われる finish_wait(&journal->j_wait_transaction_locked, &wait); goto repeat; } /* * If there is not enough space left in the log to write all potential * buffers requested by this operation, we need to stall pending a log * checkpoint to free some more log space. */ spin_lock(&transaction->t_handle_lock); needed = transaction->t_outstanding_credits + nblocks; if (needed > journal->j_max_transaction_buffers) { /* * If the current transaction is already too large, then start * to commit it: we can then go back and attach this handle to * a new transaction. */ DEFINE_WAIT(wait); jbd_debug(2, "Handle %p starting new commit...\n", handle); spin_unlock(&transaction->t_handle_lock); 同2箇所目 prepare_to_wait(&journal->j_wait_transaction_locked, &wait, TASK_UNINTERRUPTIBLE); __log_start_commit(journal, transaction->t_tid); spin_unlock(&journal->j_state_lock); schedule(); このステップで WAIT キューにつなぐ と思われる finish_wait(&journal->j_wait_transaction_locked, &wait); goto repeat; } 図 2.5-66 WAIT キュー接続位置のカーネルソース(fs/jbd/transaction.c) カーネルソースのコメント(図 2.5-66 の斜め文字部分)よりstart_this_handle内からは、 以下の2つの要因によって事象待ちとなることが分かる。 ・要因-1 現在のトランザクションがコミットのためロック中の場合、ロック解除を待つ ・要因-2 要求された処理のためのログ(変更記録)バッファが確保できない場合、他の処 理がチェックポイントに到達(ファイルデータの書き込みまでの一連の処理が終 了)し、ログスペースが解放されるのを待つ - 2-80 - 逆アセンブラを詳細に解析すれば、どちらの要因によって待ちとなっているかが分かる が、コンパイラによって最適化されたコードとなっているため、逆アセンブラ解析に慣れ ていない場合は時間がかかる。解析時間を短縮するため、どの事象が発生したことで strace プロセスが起床しているかを、先に確認する。 カーネル 2.6 では事象が起こると、その事象を待っているプロセスを起床させるために wake_up 関数がコールされる。wake_up 関数ではプロセスを RUN キューにつなぐ処理を 行い、その後 RUN キューにつながれたプロセスの中でスケジューリングが行われる。 lkstではこのイベント(wakeup_pid)をトレースでき、そのイベント引き数を確認するこ とで、どのプロセスがwake_up関数をコールしたかを確認することができる(straceを起床 させた事象は、そのプロセス実行中に発生)。lkstログ解析による起床プロセスの特定を 図 2.5-67 に示す。 $ lkstbuf print -r -E lkst_etypes -e "wakeup_pid" -f lkst.log :(省略) 1. プロセスを起床させるイベントのみ表示 event_type=wakeup_pid cpu=00, pid=00000214 time=Fri Jul 22 13:14:09.268903292 2005 2. 時刻および起床対象プロセス 時刻からイベントを特定 pid(strace の pid は 8591、16 進数では 218f)によって、イ ベントを特定 arg1=0x0000218f 00000000 : wakeup pid arg2=0x00000003 00000000 : process state arg3=0x00000000 00000000 : synchronus $ lkstla procstat -s -p 214 3. strace を起床させるプロセスの pid(214) をチェック lkst.log 4. プロセス状態変化イベントの一覧からチェ ックした pid をフィルタ Process status analyzer pid task_name count average max min 8.000000000 5.000000000 total 214 kjournald 450 6.931111111 3119.000000000 図 2.5-67 5. kjournald プロセスで事象が発生し、strace を起床していることが判明 lkst ログ解析による strace 起床プロセスの特定 この結果、トランザクションのコミットを行うkjournaldによってstraceが起床されたこと が 分 か る 。 す な わ ち 、 strace は ト ラ ン ザ ク シ ョ ン の コ ミ ッ ト の 終 了 を 待 っ て お り (start_this_handle中の事象待ち要因-1)、コミット終了によって起床されたのだと想定さ れる。また、図 2.5-64 と 図 2.5-67 より、事象待ちから事象発生までの時間は約3秒かか っており、事象(この場合はトランザクションコミット終了)の発生が遅れたことに障害 原因を限定できたことになる。 - 2-81 - (3) lkst による解析(事象待ち根本原因の追跡) 更に、トランザクションコミットの終了が遅れた原因は何かを追跡する。事象が発生し ているkjournaldプロセスの状態について、障害が発生している時刻付近を確認する(図 2.5-68 参照) 。 $ lkstla procstat -lP -p 214 lkst.log :(省略) kjournald(pid: 214)のプロセス状態の変化を 時刻順に表示 214 kjournald 214 1122005646.011219675 7.000000000 214 kjournald 214 1122005646.011227864 8.000000000 214 kjournald 214 1122005646.011233507 5.000000000 214 kjournald 214 1122005649.268884395 7.000000000 214 kjournald 214 1122005649.268887083 8.000000000 214 kjournald 214 1122005649.927378826 7.000000000 214 kjournald 214 1122005650.278798181 8.000000000 図 2.5-68 kjournald も約 3 秒事象待 ちになっている kjournald プロセス状態の確認(lkst ログの抜粋) 図 2.5-68 より、kjournaldもstraceと同様に事象待ちとなっており、事象待ちの連鎖となっ ていることが分かる。straceの場合と同様に、kjournaldについても、何の事象を待ってい るのか、どのプロセスによって起床されているのかを確認する。 同様の手順で確認した所、journal_commit_transaction 関数で WAIT キューにつながれ ており、lkstbuf プロセスによって起床されていることが分かった(詳細は省略)。 journal_commit_transaction 関数のソースコードのコメントより、kjournald プロセスが 待っている事象は、実行中の全 I/O 更新処理の終了待ちであり、lkstbuf の I/O 処理の延長 で起床されたことが分かる。 事象待ちの連鎖が終了するまで、更に遡って解析を行う。事象が発生していたlkstbufプロ セスの状態について、障害が発生している時刻付近を確認する(図 2.5-69 参照) 。 $ lkstla procstat -lP -p 8739 lkst.log :(省略) lkstbuf(pid: 8739)のプロセス状態の変化を 時刻順に表示 8739 lkstbuf 8739 1122005642.857962129 8.000000000 8739 lkstbuf 8739 1122005642.877961711 7.000000000 8739 lkstbuf 8739 1122005644.864863612 8.000000000 8739 lkstbuf 8739 1122005644.872919190 7.000000000 8739 lkstbuf 8739 1122005644.875835215 8.000000000 8739 lkstbuf 8739 1122005644.875851996 7.000000000 8739 lkstbuf 8739 1122005644.886705338 8.000000000 8739 lkstbuf 8739 1122005644.886707569 5.000000000 8739 lkstbuf 8739 1122005644.938930116 7.000000000 - 2-82 - 2箇所で事象待ち(5)に なっているが、どちらも それほど経たないうちに スケジューリング待ち (7)になっている (1箇所目) 8739 lkstbuf 8739 1122005645.399773740 7.000000000 8739 lkstbuf 8739 1122005647.571356244 8.000000000 8739 lkstbuf 8739 1122005647.573401067 5.000000000 8739 lkstbuf 8739 1122005647.579012640 7.000000000 8739 lkstbuf 8739 1122005647.673300200 7.000000000 8739 lkstbuf 8739 1122005649.268427834 8.000000000 8739 lkstbuf 8739 1122005649.268886989 7.000000000 8739 lkstbuf 8739 1122005650.297033818 8.000000000 図 2.5-69 同2箇所目 lkstbuf プロセス状態の確認(lkst ログの抜粋) 図 2.5-69 から、lkstbufプロセスでは事象待ちになった場合でも、秒オーダーでの待ちには なっていないこと、すなわち事象待ちによる連鎖がここで終了したことが分かる。 ここまでで解析できた、プロセスと事象待ちの連鎖状態は、図 2.5-70 の通り。 lkstbuf(pid: 8739) kjournald(pid: 214) strace(pid: 8591) (journal_commit_transaction) 実行中の全 I/O 更新処理が 未終了 →終了待ち write コール発行 約 3.26 秒 (start_this_handle) I/O 更新処理終了 約 2.87 秒 現在のトランザクションが ロック中 →コミット終了待ち コミット終了 write コール終了 凡例 : 処理 : プロセス処理中 : CPU および事象待ち 図 2.5-70 プロセスと事象待ちの連鎖状態 - 2-83 - 事象待ちの連鎖状態から、lkstbuf の I/O 更新処理がジャーナルのトランザクションコミッ ト処理を遅延させ、それによって strace の write が遅れたことが分かる。 ここまでの解析により、lkstbuf による大きなファイルの書き込み(63MByte をフォーマ ット変換して書き出すため、容量が増加する)の I/O 処理がジャーナル処理を輻輳/遅延さ せてしまい、それに伴い障害(write システムコールの遅延)が発生したと考えられる。 (4) lkst による解析(I/O キュー、WAIT キューからの解析結果裏付け) この仮説を実証するため、ブロックI/O関連に着目し、lkstログ解析を行う。まず、ブロ ックI/Oキューにたまっている数が多くなっていないか確認するため、ブロックI/Oキューを 確認する。確認は、図 2.5-71 の通り。 - 2-84 - $ lkstla blkqueue -s lkst.log 1. ブロック I/O キュー状態を表示する Block-IO request queue analyzer rq-addr requestqueue count average max min total percent f7ce4028 0xf7ce4028RD 4.000000000 4 1.000000000 2.000000000 0.000000000 802 1.110972569 5.000000000 0.000000000 8 0.500000000 1.000000000 0.000000000 333 3.381381381 0.198 f7ce4029 0xf7ce4028WR 891.000000000 44.000 f7ce48c8 0xf7ce48c8RD 4.000000000 0.198 f7ce48c9 0xf7ce48c8WR 1126.000000000 ブロック 2. write I/O システムコールが問題となっ キュー状態を表示 26.000000000 0.000000000 ていたので、書き込みのキューを確認 55.605 3. blkqueue の経過時間での変化をグラフ表示する。コマン ドは、下記の通り $ lkstla blkqueue -l lkst.log > blkqueue.log $ lkst_plot_log -k f7ce4029,f7ce48c9 blkqueue.log 4. 障害発生箇所はこの付近(時刻 1122005646~1122005650 秒)。 1122005645 秒くらいにある山(最大 キュー長4)が疑わしい 図 2.5-71 ブロック I/O キュー長の解析 - 2-85 - 図 2.5-71 から、時刻 1122005646 付近にブロックI/Oキュー長が長くなり山になってい る部分(キュー長は最大 4)が確認でき、この部分が疑わしいことが分かる。 キュー関係を洗う意味で、今度はWAITキュー長を確認する(図 2.5-72、図 2.5-73 参照)。 $ lkstla waitqueue -s lkst.log 1. WAIT キュー状態を表示する waitqueue length analyzer address calling_point min count average max 2 0.500000000 1.000000000 175 2.097142857 6.000000000 85 2.282352941 5.000000000 total percent c01f8d1f start_this_handle+593 0.000000000 c02c7558 1.000000000 0.178 blk_congestion_wait+70 0.000000000 c0384bf4 367.000000000 65.302 unix_wait_for_peer+6d 0.000000000 194.000000000 34.520 2. キュー最大長が長いものに着目し... (ここでは最大長 0 の項目は省略し、表示して いない) 3. 関連しそうなキューを確認する 関数名から、関連しそうなキューを 確認する 4. waitqueue の経過時間での変化をグラフ表示する。コマ ンドは、下記の通り $ lkstla waitqueue -l lkst.log > waitqueue.log $ lkst_plot_log -k c01f8d1f,c02c7558 waitqueue.log 5. 障害発生箇所はこの付近(時刻 1122005646~1122005650 秒) 図 2.5-72 WAIT キュー長の解析(その1) - 2-86 - 6. キュー表示の場合、値 0 は X 軸に隠れて表示されないため、 ラインスタイルを変更して表示する。コマンドは、下記の通り $ lkst_plot_log -k c01f8d1f,c02c7558 -l points waitqueue.log 7. ファイル書き出し後 1122005645 秒くらいからブロック I/O が詰まり出し(blk_congestion_wait:ブロック I/O キュー空き 待 ち : × 点 )、 そ の 後 で ト ラ ン ザ ク シ ョ ン コ ミ ッ ト (start_this_handle:トランザクションコミット待ち:+点)も 詰まってしまったと考えられる 図 2.5-73 WAIT キュー長の解析(その2) 図 2.5-72、図 2.5-73 から、ブロックI/Oキューが詰まり出し、その後でトランザクション コミット処理が詰まってしまったことが分かり、先の仮説が正しかったことが確認できる。 write コール実行遅延の原因は、下記の2つの複合要因によるものだった。 ・要因-1 lkst でトレース実行中にバッファ書き出しを行ってしまっていた ・要因-2 strace のログ書き出しが、大きなファイルの I/O 処理(本事例では lkst バッファ の書き出し)がある場合、それに引っ張られて遅延する 要因-1 に関しては、トレース実行中にバッファ書き出しを行っても、lkst 自身のバッファ 書き出しはトレースされないだろう、という思い込みがあった。実際にはバッファ書き出 しの最中に発生したイベントを更に記録しようとするループ状態に陥ってしまい、なかな かファイル書き出しが終了しない、という状態になってしまう。 要因-2 に関しては、本事例の障害は lkst のバッファ書き出しによる I/O 高負荷状態で発生 したが、lkst トレース中にバッファ書き出しを行わないようにした場合であっても、大き なファイルを書き出すようなアプリケーションのトレース時には、同じ障害が発生すると 考えられる。 - 2-87 - 次に、処理時間が長い他のシステムコールについても障害要因が同じかどうか解析するた め、図 2.5-63 中の他のシステムコールについても解析を行う(表 2.5-13 参照)。 表 2.5-13 strace で 100msec 以上掛かったシステムコール中のプロセス状態 項 システム 開始時刻※1 処理時間 プロセス状態 遅延タ 番 コール ※2 イプ 1 write 18.357494243 0.015721569 7、8 C 2 write 28.987744834 0.361722669 7、8 B 3 ptrace 29.350419772 0.412785495 7、8 B 4 ptrace 45.402513623 0.558999814 7、8 C 5 write 46.402062455 3.884396753 5、7、8 A 6 read 53.287346371 0.012485473 7、8 B 7 read 54.302765216 0.013471801 7、8 B ※1:開始時刻の秒数は下2桁以降のみ表示 ※2:プロセス状態の意味は次の通り 5:割り込み不可状態で事象待ち、7:スケジューリング待ち、8:実行中 この表で、項番 5 が既に解析済みの、トランザクションコミットの待ち合わせを行ってい た write である(タイプ A)。 その他のシステムコール中の lkst プロセス状態は、事象待ちになっておらず、単純にスケ ジューリング待ちとなっていることが分かる。これらのスケジューリング待ち中に実行状 態となっているプロセスを調べた所、以下の2パターンがあることが分かった。 ・多数のプロセス(stress 等)が実行 --- タイプ B ・ほとんどの時間を特定プロセスが CPU を占有 --- タイプ C ※特定プロセスは、kblockd/0、kjournald といった重い I/O 処理を行うプロセス これまでの解析によって、strace がトレース対象プロセスを遅延させる障害の原因は、 下記によるものだということが分かる。 ・原因-1 strace のログ書き出しが、大きなファイルの I/O 処理がある場合、それに引っ張 られて遅延する(タイプ A) ・原因-2 多数のプロセス実行によるスケジューリングでの遅延(タイプ B) ・原因-3 I/O 処理プロセスの CPU 占有による遅延(タイプ C) 2.5.2.4 対策 まず、lkst でトレースを行う場合は、バッファ書き出しをトレース中に行うのではなく、 トレース停止後に行うよう変更する必要がある。前述の手順中、バッファの書き出しを行 う以下の部分を変更することで、トレース停止後にバッファ書き出しを行うようにする。 - 2-88 - <<< 変更前 >>> e. lkst のバッファをファイルに出力する # lkstbuf read -f lkst.log <<< 変更後 >>> e. lkst トレースを停止した後で lkst のバッファをファイルに出力する # lkst stop # lkstbuf read -f lkst.log 原因-1 strace のログ出力遅延に関しては、ログ出力先を ramfs/tmpfs 上のファイルにす ることによって改善できる。strace ログ出力先を ramfs にする際の手順は、下記の通り。 a. ramfs をマウントする(スーパーユーザで行う必要あり) # mount -t ramfs ramfs /mnt/ramfs b. strace を実行(前述の手順中で、ログ出力先を変更した場合のもの) $ strace -f -F -ttt -T -o /mnt/ramfs/strace.log sar 1 0 原因-2、3 に関しては、カーネル内のスケジューリングや I/O 処理に依存しており、対策 を施すことは難しい。nice 値変更等のチューニングを行うことも考えられるが、トレース 対象プロセスの本来の挙動を変えてしまう可能性があるため、問題がある。 以上により、完全な対策は不可能であるため、改善策として strace ログ出力先を ramfs 上 のファイルとすることとした。本事例の再現手順において、strace のログ出力先を ramfs として障害を再現させた所、strace の write で長時間かかっていた部分(タイプ A)は解消 されていることが確認できた。 - 2-89 - 2.5.3 性能障害 性能障害の場合、oprofile などを利用してボトルネックを発見する。 表 2.5-14 I/O 負荷の高いベンチマークの性能障害の概要 番号 現象 2.5.3 解決日 2005/xx/xx I/O 負荷の高いベンチマークにおいて性能上の問題が発見された。 分類 発生環境 2005/xx/xx 発生日 性能障害 OS MIRACLE LINUX V4.0 beta CPU Xeon MP メモリ 6GB ハードディスク SCSI ネットワーク 原因 CPU キャッシュミスが多発していた。 対策 カーネルパッチを作成した。 解析手法 oprofile を利用した。 2.5.3.1 分析 oprofile でキャッシュミスを測定する。 例: # opcontrol -e=BSQ_CACHE_REFERENCE:3000:0x200:1:1 ここで BSQ_CACHE_REFERENCE が測定すべきイベントである。3000 は当該イベン トが 3000 回発生したらサンプリングする。0x200 はイベントマスクで L3 キャッシュミス を測定する。次の 1 はカーネルモードをサンプリングすることを示し、最後の 1 はユーザ ーモードをサンプリングする事を示す。したがって上記例はカーネル、ユーザー両方とも プロファイリングする。 例:oprofile の詳細レポート。opreport -d の出力例 Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x300 (multiple flags) count 3000 vma samples % image name app name symbol name c01bf3c0 57131 58.6964 vmlinux vmlinux __copy_from_user_ll c01bf3e7 2 0.0035 c01bf3f0 53761 94.1013 c01bf3f2 1786 3.1261 c01bf3f4 13 0.0228 c01bf3f6 1157 2.0252 c01bf401 3 0.0053 c01bf402 369 0.6459 c01bf404 17 0.0298 c01bf405 23 0.0403 pattern1-0-cpu4-08112022/detail.out ここで、c01bf3f0 でキャッシュミスを多発している事がわかる。vmlinux を逆アセンブ - 2-90 - ルすることによって当該アドレスが何をしているのかがわかる。 # objdump -S vmlinux-2.6.9-11.11AX 当該ソースコードは下記の通り。 c01bf3c0 <__copy_from_user_ll>: c01bf3c0: 57 c01bf3c1: 83 f9 3f c01bf3c4: 89 c7 c01bf3c6: 56 c01bf3c7: 89 d6 c01bf3c9: 76 0a c01bf3cb: 31 d0 c01bf3cd: 85 05 00 a9 43 c0 c01bf3d3: 75 23 c01bf3d5: 89 c8 c01bf3d7: 83 f9 07 c01bf3da: 76 18 c01bf3dc: 89 f9 c01bf3de: f7 d9 c01bf3e0: 83 e1 07 c01bf3e3: 29 c8 c01bf3e5: f3 a4 c01bf3e7: 89 c1 c01bf3e9: c1 e9 02 c01bf3ec: 83 e0 03 c01bf3ef: 90 c01bf3f0: f3 a5 c01bf3f2: 89 c1 c01bf3f4: f3 a4 c01bf3f6: eb 09 c01bf3f8: 89 f8 c01bf3fa: e8 e7 fe ff ff c01bf3ff: 89 c1 c01bf401: 5e c01bf402: 89 c8 c01bf404: 5f c01bf405: c3 c01bf406: 90 c01bf407: 90 push %edi cmp $0x3f,%ecx mov %eax,%edi push %esi mov %edx,%esi jbe c01bf3d5 <__copy_from_user_ll+0x15> xor %edx,%eax test %eax,0xc043a900 jne c01bf3f8 <__copy_from_user_ll+0x38> mov %ecx,%eax cmp $0x7,%ecx jbe c01bf3f4 <__copy_from_user_ll+0x34> mov %edi,%ecx neg %ecx and $0x7,%ecx sub %ecx,%eax repz movsb %ds:(%esi),%es:(%edi) mov %eax,%ecx shr $0x2,%ecx and $0x3,%eax nop repz movsl %ds:(%esi),%es:(%edi) **この部分 mov %eax,%ecx repz movsb %ds:(%esi),%es:(%edi) jmp c01bf401 <__copy_from_user_ll+0x41> mov %edi,%eax call c01bf2e6 <__copy_user_zeroing_intel> mov %eax,%ecx pop %esi mov %ecx,%eax pop %edi ret nop nop 上記ソースコードの repz movsl %ds:(%esi),%es:(%edi) がキャッシュミスを多発してい る事がわかる。 I/O 負荷の高いベンチマークで write(2)を多発するようなアプリケーションの場合、 filemap_copy_from_user()で__copy_from_user()が呼ばれている。ある関数がどこから呼ば れているかは OProfile のコールグラフ機能によって容易に発見できるので、それを利用し てどこから copy_from_user が呼ばれているか調査した。 # opcontrol --callgraph=#depth 図 2.5-74 call graph の設定例 opcontrol で#depth に測定すべき深さを指定する。コールグラフの計測はオーバヘッド がかかるので注意が必要である。 計測後 opstack でコールグラフのレポートを作成し分析する。 - 2-91 - # opstack -f -p /lib/modules/$(uname -r) > ${saveDir}/callgraph.out 2>&1 図 2.5-75 call graph のレポート作成 さて__copy_from_user_ll()の実行例は下記のとおりである。 0 0 6 8.8e-04 vmlinux copy_from_user 4157 21.8433 325670 47.5335 vmlinux __generic_file_aio_write_nolock 14874 78.1567 359462 52.4656 vmlinux generic_file_buffered_write 241263 1 13.7168 1 100.000 5.7e-05 0 vmlinux __copy_from_user_ll 0 vmlinux __copy_user_zeroing_intel 図 2.5-76 コールグラフ(__copy_from_user_ll) copy_from_user()/__generic_file_aio_write_nolock()/generic_file_buffered_write() と い う関数から呼ばれていることが分かる。 filemap_copy_from_user(struct page *page, unsigned long offset, const char __user *buf, unsigned bytes) { char *kaddr; int left; kaddr = kmap_atomic(page, KM_USER0); left = __copy_from_user(kaddr + offset, buf, bytes); kunmap_atomic(kaddr, KM_USER0); if (left != 0) { /* Do it the slow way */ kaddr = kmap(page); left = __copy_from_user(kaddr + offset, buf, bytes); kunmap(page); } return bytes - left; } 通常、write(2)の場合、ユーザー空間からカーネル空間へデータをコピーした後、すぐに ディスクに書き出されるのではなく、非同期にディスクに書き出される。従ってユーザー 空間からカーネル空間へコピーされたデータがすぐアクセスされる可能性は低い。 表 2.5-15 Pentium4/Xeon におけるキャッシュのサイズ キャッシュ キャッシュサイズ L1(一次)キャッシュ 8KB L2(二次)キャッシュ 512KB L3(三次)キャッシュ 1 ないし 2MB - 2-92 - 十分大きなファイルを書き出す場合、データはキャッシュにはのりきらないので当然キ ャッシュミスを起こす。特にメモリへの書き込みの場合、すぐにアクセスされないのであ るから、キャッシュにのせる意味はない。キャッシュにのせる必要のないデータをキャッ シュにのせる事によってすぐに必要になるであろうデータを追い出してしまう事を cache pollution と呼ぶ。上記の例は典型的な cache pollution が発生している。 作成したパッチの部分 + + + + + + + + + + + + + + + 略 __asm__ __volatile__( " "0: " " "1: " "2: "21: " " "3: "31: " " .align 2,0x90\n" movl 32(%4), %%eax\n" cmpl $67, %0\n" jbe 2f\n" movl 64(%4), %%eax\n" .align 2,0x90\n" movl 0(%4), %%eax\n" movl 4(%4), %%edx\n" movnti %%eax, 0(%3)\n" movnti %%edx, 4(%3)\n" movl 8(%4), %%eax\n" movl 12(%4),%%edx\n" movnti %%eax, 8(%3)\n" movnti %%edx, 12(%3)\n" そこで、cache pollution を発生させないため、レジスタからメモリへ転送する時、キャ ッシュをバイパスする命令(MOVNTI 命令)を利用した API(__copy_from_user_ll_nocache) を作成し、filemap_copy_from_user()でそれを利用するようにした。 その結果、 zキャッシュミス(BSQ_CACHE_REFERENCE,0x200) 改良版/オリジナル版 16153/55033=29.35% (約 70%減) zクロック数(GLOBAL_POWER_EVENTS) 改良版/オリジナル版 1234232/1705473=72.37%(約 30%減) z__copy_from_user_ll_nocache(改良版)と__copy_from_user_ll のキャッシュミス 1/37117=0 改良版 pattern9-0-cpu4-0-09031504/summary.out 200/nocache 16153 pattern9-0-cpu4-0-09031508/summary.out 3f/nocache 1234232 pattern9-0-cpu4-0-09031512/summary.out GLOBAL_POWER_EVENTS 1513271 オリジナル版 pattern9-0-cpu4-0-09031546/summary.out 200/orig 55033 pattern9-0-cpu4-0-09031549/summary.out 3f/orig 1304147 pattern9-0-cpu4-0-09031553/summary.out GLOBAL_POWER_EVENTS 1705473 cache pollution の場合は、MOVNTI 命令のようなキャッシュをバイパスする命令を利用 すると効果がある事が確認できた。 - 2-93 - 2.6 フリーズ 2.6.1 フリーズ障害の解析 実際にフリーズを起こした障害を例にあげ、採取されたダンプからの解析と対策を 以下に報告する。 2.6.1.1 概要 本障害とその対策の概要を表 2.6-2 に示す。 表 2.6-1 高優先度プロセスの異常稼動による現象の概要 番号 2.6.1 現象 性能情報採取コマンド(優先度:高)を実行中にフリーズが発生した 分類 フリーズ 発生環境 OS Redhat AS4.0 update1 CPU Xeon MP 3.0G × 1 メモリ 4GBytes ハードディスク 72Gbytes ネットワーク IntelPro1000 原因 発生日 2005/xx/xx 解決日 2005/xx/xx 情報採取パッケージ(sysstat)が未導入であったため、情報採取コマンド を実行する高優先度の性能情報採取シェルスクリプト(status.sh)の 子プロセスが、wait なしでループしたため 対策 情報採取パッケージ(sysstat)コマンドの導入 解析手法 (1) 解析資料採取 (2) 現象発生時プロセス特定 (3) 現象発生時のプロセス詳細確認 (4) ログファイル確認 (5) 原因特定 2.6.1.2 障害情報収集と初期切り分け 性能情報採取ツール(status.sh)を実行したところ、実行した端末、コンソールへの 応答がなくなった。 コンソールからのコマンド入力に対して応答がないフリーズの場合、SysRq キー/ NMI イ ン タ ー フ ェ ー ス に よ り ダ ン プ 採 取 を 行 う 。 シ ス ロ グ フ ァ イ ル (/var/log/messages)及び、その時稼動していたアプリケーションのログファイルを採 取しておく。 - 2-94 - 2.6.1.3 解析 以下の手順で解析を行った。 (1) 解析資料採取 次の資料の採取を行う。 ・ダンプ(SysRq キーにより、diskdump で採取:diskdump 導入/設定方法は、 3.6.1.1 を参照のこと) ・性能情報採取ツールのログファイル (2) 現象発生時のプロセス特定 ダンプ解析ツール Alicia でダンプ解析を開始する。 # alicia -crash map-file vmlinux dump-file KERNEL: /usr/src/linux-2.6.9-11ELsmp-devmem/vmlinux DUMPFILE: ./vmcore CPUS: 1 ←② DATE: Sun Sep 11 04:45:11 2005 UPTIME: 49 days, 17:01:52 ←① ←① LOAD AVERAGE: 3.39, 0.96, 0.34 TASKS: 74 NODENAME: redhatas4u1 RELEASE: 2.6.9-11ELsmp-devmem ←② VERSION: #1 SMP Sun Sep 11 03:06:25 JST 2005 MACHINE: i686 ←② MEMORY: 2 GB (2393 Mhz) ←② PANIC: "Oops: 0002 [#1]" (check log for details) PID: 21191 ←③ COMMAND: "echo" ←③ TASK: dca7d230 ←③ [THREAD_INFO: de469000] ←③ CPU: 0 STATE: TASK_RUNNING (PANIC) alicia> 図 2.6-1 Alicia 起動時の出力メッセージ Aliciaの最初の出力 (図 2.6-1)より、 ① ダンプ採取された時間、稼動時間 ② システム情報(カーネルのリリース、バーション、CPU 数、メモリ量等) ③ パニック情報(Oops タイプ、PID、コマンド、タスク等) が得られる。詳細なパニック情報を得るために、log コマンドを入力する。 - 2-95 - alicia> log (途中 略) SysRq : Crashing the kernel by request Unable to handle kernel NULL pointer dereference at virtual address 00000000 printing eip: c0201580 *pde = 20688001 Oops: 0002 [#1] SMP Modules linked in: md5(U) ipv6(U) parport_pc(U) lp(U) parport(U) autofs4(U) i2c_ dev(U) i2c_core(U) sunrpc(U) scsi_dump(U) diskdump(U) dm_mod(U) button(U) batter y(U) ac(U) uhci_hcd(U) hw_random(U) e1000(U) floppy(U) sg(U) ext3(U) jbd(U) mpts csih(U) mptbase(U) sd_mod(U) scsi_mod(U) CPU: 0 EIP: 0060:[<c0201580>] EFLAGS: 00010046 Not tainted VLI (2.6.9-11ELsmp-devmem) EIP is at sysrq_handle_crash+0x0/0x8 eax: 00000063 ebx: c032fa94 ecx: f691f000 edx: de469e44 esi: 00000063 edi: f691f000 ebp: de469e44 esp: de469d40 ds: 007b es: 007b ss: 0068 Process echo (pid: 21191, threadinfo=de469000 task=dca7d230) Stack: c02016c2 c02e782b c02e8c3c 00000006 00000001 f7d2d180 00000001 0000002e c01fc4a8 de469e44 c032de20 f7d24064 f7d2d180 0000002e c025c231 00000001 00000001 0000002e f7d24064 00000001 00000000 c025eeef 00000001 0000002e 図 2.6-2 log コマンドの出力メッセージ 図 2.6-2 のlogコマンドの応答より、このダンプは、SysRqキーの入力により採取され たことが確認できる。 フリーズは、現象発生時に実行中のプロセスが起因して発生している可能性が高い ので、原因特定の第一歩として、ps コマンドを実行し、現象発生時に実行中だったプ ロセスを確認する。 - 2-96 - alicia> ps PID PPID CPU TASK ST %MEM VSZ RSS 0 0 0 c0314a60 RU 0.0 0 0 1 0 0 f7f21630 RU 0.0 2004 552 (途中 COMM [swapper] init 現象発生時に稼動してい 略) たプロセスの親プロセス の親プロセス 3619 3587 0 dc4da030 RU 0.0 2724 924 top 3620 2708 0 dc4db630 IN 0.1 7676 2168 sshd 3622 3620 0 dc4db0b0 IN 0.1 5300 1164 sftp-server 3641 3549 0 dc4dab30 IN 0.1 6768 1124 status.sh 3699 3641 0 dc4da5b0 IN 0.0 2388 860 sh 3705 3699 0 dc42abb0 IN 0.0 2640 464 sleep 3716 3641 0 dc42b130 IN 0.0 4124 860 sh 3720 3716 0 dc42b6b0 IN 0.0 2884 464 sleep 3734 3641 0 dc42a630 IN 0.0 3724 848 sh 3742 3734 0 dc42a0b0 IN 0.0 3728 464 sleep 3752 3641 0 dcaa5730 IN 0.0 3708 852 sh 3756 3752 0 dcaa51b0 IN 0.0 3164 460 sleep 3770 3641 0 dcaa4c30 IN 0.0 3292 848 sh 現象発生時に稼動 3774 3770 0 dcaa46b0 IN 0.0 3108 464 sleep していたプロセス 3788 3641 0 dcaa4130 IN 0.0 2924 852 sh の親プロセス 3797 3788 0 dca7d7b0 IN 0.0 3660 464 sleep 3815 3641 0 dca7ccb0 IN 0.0 4120 856 sh 3865 3641 0 dca7c730 IN 0.0 2136 860 sh 3870 3865 0 dca7c1b0 IN 0.0 2320 464 sleep “>”の付いたプロセス 4056 3641 0 dca77830 IN 0.0 2472 856 sh が現象発生時に稼動 4060 4056 0 dca772b0 IN 0.0 2040 508 vmstat していたプロセス 5054 3641 0 dca76d30 IN 0.0 2604 460 sleep > 21191 3815 0 dca7d230 RU 0.0 1368 180 echo (性能情報採取ツールの メインプロセス) alicia> 図 2.6-3 ps コマンドの出力メッセージ 図 2.6-3 より、システムがフリーズしてダンプを採取した時点で、 ・ 稼動していたプロセス(PID:21191)は、“echo”コマンド実行 ・ その親プロセス(PID:3815)は、シェルスクリプトを実行中 ・ その親プロセス(PID:3641)は、フリーズが発生する直前に投入した性能情 報採取ツール(status.sh) - 2-97 - であることがわかる。 (3) 現象発生時のプロセス詳細確認 次に各プロセスの Cputime を計算して、使用量の大きい順番にソートして表示する LDAS(Alicia の拡張コマンド)を使用して、Cputime をどのプロセスが多く消費し ているかを調べる。 alicia> ps_cpu | more PID PPID CPU TASK ST %MEM VSZ RSS Cputime COMM 0 0 0 c0314a60 RU 0.0 0 0 3815 3641 0 dca7ccb0 IN 0.0 4120 856 1 0 0 f7f21630 RU 0.0 2004 552 2853 1 0 c2386230 IN 0.8 58 1 0 f7cd7730 IN 0.0 0 0 2989 1 0 f69523b0 RU 0.3 9116 5872 515 hald 2660 1 0 f6997630 RU 0.2 11456 3772 258 cupsd 223 1 0 f7cd66b0 RU 0.0 0 0 162 [kjournald] 2964 1 0 c239a830 IN 0.1 2948 1208 128 dbus-daemon 3641 3549 0 dc4dab30 IN 0.1 6768 1124 106 status.sh 2935 1 0 f6a965b0 IN 0.2 5992 3336 68 xfs 3619 3587 0 dc4da030 RU 0.0 2724 924 68 top 57 4 0 f7c700b0 IN 0.0 0 0 2708 1 0 f6952930 IN 0.1 5640 1652 57 sshd 3547 2708 0 df536630 IN 0.1 7744 2196 41 sshd 19064 17632 187081 [swapper] 3994 sh 708 init 690 cannaserver 609 [kswapd0] -1 59 [pdflush] 図 2.6-4 ps_cpu(Alicia の LDAS)コマンドの出力メッセージ 最も多く Cputime を使用しているのは、swapper である。swapper は、仮想記憶 を司るカーネルプロセスで、PID:0 で起動している。このプロセスは、アイドル状 態でも他のプロセスより、Cputime を使用しているのが経験的にわかっている。今回 は、フリーズ直前に入力した性能情報採取ツール status.sh に関連するプロセスが 2 番目に Cputime を多く使用しているので、そのプロセス(PID:3815)から調べて、 それに関連するプロセスも念のため、調べてみる。 性能情報採取ツール(status.sh)に関連するプロセス3つについて、ps –t コマン ドで、それぞれの Cputime を調べてみる。LDAS ps_cpu では、このコマンドで応答 される USER TIME と SYSTEM TIME の合計が Cputime として表示される。 alicia> ps -t 3815 - 2-98 - PID: 3815 TASK: dca7ccb0 CPU: 0 COMMAND: "sh" RUN TIME: 183930010746 days, 10:02:11 START TIME: 2555191149513933013 PID:3815 が 使 用 し て い る USER TIME: 929 USER/SYSTEM TIME SYSTEM TIME: 3065 alicia> ps -t 21191 PID: 21191 TASK: dca7d230 CPU: 0 COMMAND: "echo" RUN TIME: 164461182487 days, 01:15:15 PID:21191 が 使 用 し て い る START TIME: 4237297911123149033 USER/SYSTEM TIME USER TIME: 0 SYSTEM TIME: 1 alicia> ps -t 3641 PID: 3641 TASK: dc4dab30 CPU: 0 COMMAND: "status.sh" RUN TIME: 179188446388 days, 01:34:27 START TIME: 2964862310075597009 PID:3641 が 使 用 し て い る USER TIME: 34 USER/SYSTEM TIME SYSTEM TIME: 72 alicia> 図 2.6-5 ps –t コマンドの出力メッセージ 図 2.6-4/図 2.6-5 より、プロセス(PID:3815) が実行しているシェルスクリプトが異 常に Cputime(USER / SYSTEM TIME) を使用していることが確認できる。 まず、プロセス(PID:3815)のシェルスクリプトでは、どのようなファイルをオープ ンしているかを調べてする。これには、files コマンドを使用する。 alicia> files 3815 PID: 3815 ROOT: / TASK: dca7ccb0 CPU: 0 COMMAND: "sh" CWD: /opt/status PID:3815 がオープンし ているファイル(iostat FD FILE DENTRY INODE TYPE PATH 0 ebebe580 f7d9d804 f7d9b93c CHR /dev/null 1 f2299280 ebebf5a4 f6a68cc8 CHR /dev/pts/0 2 ebebec80 f7d9d804 f7d9b93c CHR /dev/null 255 ebebe380 f228689c df53c770 REG /var/tmp/statdir_3641/iostatxdcmd を定期的に起動している シェルスクリプト) alicia> 図 2.6-6 files コマンドの出力メッセージ オープンしているファイルの中にiostatを定期的に起動しているシェルスクリプト があることがわかる。(図 2.6-6) - 2-99 - /var/tmp/statdir_3641/iostatxdcmd 次に、プロセス(PID:3815)の情報を得るために、task_struct 構造体を、struct コマンドを使用して調べてみる。task_struct 構造体は、プロセス毎に生成され、プ ロセスを管理するために使用される。 alicia> ps 3815 PID PPID CPU TASK ST %MEM VSZ RSS COMM 3815 3641 0 dca7ccb0 IN 0.0 4120 856 sh alicia> alicia> struct task_struct dca7ccb0 | more struct task_struct { state = 1, thread_info = 0xdeb17000, usage = { counter = 10 }, flags = 4194560, ptrace = 0, lock_depth = -1, prio = 0, static_prio = 120, run_list = { next = 0x100100, prev = 0x200200 }, 静的優先度が 99(高優先度)に (途中 略) 設定されている。 rt_priority = 99, (途中 略) 図 2.6-7 PID:3815 に対する ps コマンドの出力メッセージ 図 2.6-7 より、このプロセスの優先度(rt_priority)が 99 に設定されていることがわか る。この優先度は、通常のプロセスでは、静的優先度 0 が設定されているが、このプ ロセスは、処理の優先度を上げるために、静的優先度が 99 に設定されている。 ここまでの解析で、プロセス(PID:3815)が優先度を上げたシェルスクリプトを実 行していて、Cputime を異常に多く使用していることが判った。そこで、このプロセ スがどのような処理を実際に行っているかをシェルスクリプトや、その実行結果のロ - 2-100 - グファイルから解析する。 (4) ログファイル確認 プロセス(PID:3815)がどのような処理を行っていたかを確認するために、その親 プロセスである性能情報採取ツールのメインプロセス(status.sh)のシェルスクリプ トの内容を確認してみる。その結果、次のような採取コマンドを高優先度(静的優先 度値を上げている)で実行していることがわかった。 ・sar ・mpstat ・iostat そこで、上記採取コマンドが出力している実行時のログファイルを確認したところ、 以下のことがわかった。 上記採取コマンドの起動方法およびログファイルは次のとおり。ログ採取のディレ クトリィ(/var/tmp/statdir_3641/)は、メインプロセス(status.sh)が作成し、各 コマンド実行時に指定している。sar、mpstat コマンドは、INTERVAL の間隔で、 COUNT 回数まで実行するのに対して、iostat コマンドは、採取データを編集するツ ールで編集しやすいようにしているため、INTERVAL の間隔指定をし、while 文で外 側のループで複数回実行させている。 ● sar の起動方法 # /usr/bin/sar -o /var/tmp/statdir_3641/sar.log INTERVAL COUNT >/dev/null 2>&1 & ● mpstat の起動方法 # /usr/bin/mpstat -P ALL INTERVAL COUNT >>/var/tmp/statdir_3641/mpstat.log 2>/dev/null & ● iostat の起動方法 # sh /var/tmp/statdir_3641/iostatxdcmd 2>/dev/null & # シェルスクリプト(/var/tmp/statdir_3641/iostatxdcmd) while [ 1 ] do /bin/echo iostat /bin/echo INTV /bin/date >>/var/tmp/statdir_3641/iostat_xd.log /usr/bin/iostat >>/var/tmp/statdir_3641/iostat_xd.log INTERVAL >>/var/tmp/statdir_3641/iostat_xd.log -x -d INTERVAL 2 >>/var/tmp/statdir_3641/iostat_xd.log done /var/tmp/statdir_3641/以下に採取されるはずの各種ログファイルを確認した結果、採 取 コ マ ン ド ( sar 、 mpstat ) の ロ グ フ ァ イ ル ( /var/tmp/statdir_3641/sar.log 、 - 2-101 - mpstat.log)がないことおよび採取コマンド(iostat)が正常結果を出力していない ことが確認できた。 (5) 原因特定 iostat コマンドがエラーになった原因を調べるために、iostat コマンドに関する情 報採取を行う。そのために、まず、iostat コマンドをコマンドラインから入力してみ ると、“iostat:command not found”と表示され、iostat コマンドが導入されていな いことが判明した。メインプロセスから起動される各コマンドのうち、sar、mpstat コマンドは 1 回の実行でエラーになればそこで終了してしまうが、iostat コマンドの 場合、コマンド実行がエラーになっても、その外側の while 文のループが wait なし で繰り返し続けることになる。しかもその実行は、高優先度に設定されているため、 他のプロセスが処理されなくなり、フリーズ状態に陥ったと考えられる。本システム には iostat が含まれる sysstat パッケージが導入されていないと仮定し、rpm コマン ドで sysstat パッケージの導入確認を実施した結果、該パッケージが導入されていな いことが明らかになった。 2.6.1.4 対策 sysstat パッケージを rpm コマンドで導入し、性能情報採取ツール(status.sh) でシステムがフリーズすることなく、性能情報を採取することを確認した。 また、性能情報採取ツールのシェルスクリプトを変更し、実行に必要な各コマン ドが導入されているかを判断するように改良した。 - 2-102 - 2.7 カーネルパニック 2.7.1 カーネルパニック障害の解析 実際にカーネルパニックを起こした障害を例にあげ、採取されたダンプファイルから の解析と対策を以下に報告する。 2.7.1.1 概要 本障害とその対策の概要を 表 2.7-1 に示す。 表 2.7-1 メモリ破壊によるカーネルパニックの概要 番号 2.7.1 現象 突然、カーネルパニックが発生した 分類 カーネルパニック 発生環境 OS Red Hat AS4.0 update1 CPU Xeon 2.4GHz×2 メモリ 2Gbyte ハードディスク 72Gbyte ネットワーク IntelPro1000 発生日 2005/xx/xx 原因 ハードウェア障害でメモリ破壊 対策 メモリ交換 解析手法 (1) 解析資料の採取 (2) 現象確認 (3) 障害発生時の命令確認 (4) 逆アセンブルリスト (5) 原因特定 解決日 2005/xx/xx 2.7.1.2 障害情報収集と初期切り分け カーネルパニックの場合は、まず、ダンプファイルが採取されているかを確認する。 システムはカーネルパニック時にダンプが採取されるように設定されていなければ ならないが、各ダンプ採取ツールには、以下のようにダンプが採取される方法に違い がある。 (1) diskdump/netdump は、カーネルパニック後のリブート後に、/var/crash ディレクトリ にダンプが採取される。 (2) LKCD は、カーネルパニック後のリブート後に、/var/log/dump ディレクトリにダンプ が採取される。 (3) kdump は、カーネルパニック時に、ダンプ採取専用のカーネルが起動される。 /proc/vmcore にダンプ・イメージがアクセスできるようになっているので、手動で保存 - 2-103 - する。 (4) mkdump は、カーネルパニック時に、ダンプ採取専用カーネルが起動される。ダンプ 採取後に、通常のカーネルが起動され、ダンプパーティションにダンプが採取される。 2.7.1.3 解析 以下の手順で解析を行った。 (1) 解析資料の採取 次の資料が採取されているか確認する。 ・ダンプ(diskdump で採取:diskdump の導入/設定方法は、3.6.1.1 を参照) (2) 現象確認 ダンプ解析ツール Alicia でダンプ解析を開始する。 # alicia –crash map vmlinux dump-file KERNEL: /usr/src/linux-2.6.9-11ELsmp-devmem/vmlinux DUMPFILE: /var/crash/127.0.0.1-2005-09-11-03:29/vmcore CPUS: 2 ←② DATE: Sun Sep 11 03:29:59 2005 UPTIME: 00:09:08 ←① ←① LOAD AVERAGE: 0.01, 0.13, 0.16 TASKS: 61 NODENAME: redhatas4u1 RELEASE: 2.6.9-11ELsmp-devmem ←② VERSION: #1 SMP Sun Sep 11 03:06:25 JST 2005 MACHINE: i686 ←② MEMORY: 2 GB (2392 Mhz) ←② PANIC: "Oops: 0002 [#1]" (check log for details) PID: 3297 ←③ ←③ COMMAND: "perl" TASK: f7451930 ←③ [THREAD_INFO: e87de000] ←③ CPU: 0 STATE: TASK_RUNNING (PANIC) alicia> 図 2.7-1 Alicia 起動時の出力メッセージ Aliciaの最初の出力(図 2.7-1)より、 ① ダンプ採取された時間、稼動時間 - 2-104 - ② システム情報(カーネルのリリース、バーション、CPU 数、メモリ量等) ③ パニック情報(Oops タイプ、PID、コマンド、タスク等) が得られる。これにより、perl コマンドを実行中にダンプが採取されていたことが判 る。次に、詳細なパニック情報を得るために、log コマンドを入力する。 log コマンドより、障害発生時の”Oops”の情報を確認することができる。log コマン ドは、パニック発生時にメモリ上に残されたシステムログのバッファの内容を表示す るコマンドである。Linux カーネルはシステム障害を検知し、パニックによってシス テム停止を行う場合、どのような障害を検知したかをシステムログに出力している。 alicia> log 参照しようとしたアドレス (途中 略) Unable to handle kernel NULL pointer dereference at virtual address 0000008f printing eip: 障害が発生したアドレス c0168a18 *pde = 27f93001 Oops: 0002 [#1] SMP Modules linked in: scsi_dump(U) diskdump(U) md5(U) ipv6(U) parport_pc(U) lp(U) p arport(U) autofs4(U) i2c_dev(U) i2c_core(U) sunrpc(U) dm_mod(U) button(U) batter y(U) ac(U) uhci_hcd(U) hw_random(U) e1000(U) floppy(U) sg(U) ext3(U) jbd(U) mpts csih(U) mptbase(U) sd_mod(U) scsi_mod(U) CPU: 0 EIP: 0060:[<c0168a18>] EFLAGS: 00010287 Not tainted VLI (2.6.9-11ELsmp-devmem) EIP is at sys_flock+0x0/0x119 eax: 0000008f ebx: 00000003 ecx: 00000002 edx: 0000007b esi: 00000002 edi: 093902f8 ebp: e87de000 esp: e87defc0 ds: 007b es: 007b ss: 0068 Process perl (pid: 3297, threadinfo=e87de000 task=f7451930) Stack: c02c736b 00000003 00000002 04598c0c 00000002 093902f8 bffe2d28 0000008f 0000007b 0000007b 0000008f 004737a2 00000073 00000282 bffe2cf8 0000007b Call Trace: [<c02c736b>] syscall_call+0x7/0xb Code: 00 fe ff ff 8d 54 24 20 8d 43 1c e8 95 6c fb ff 85 f6 89 f7 0f 84 56 ff ff ff 89 d8 e8 0f ea ff ff 83 c4 40 89 f8 5b 5e 5f 5d c3 <00> 00 f7 ff ff ff 57 56 53 57 8b 44 24 18 8b 5c 24 1c e8 1e e3 alicia> 図 2.7-2 log コマンドの出力メッセージ - 2-105 - 図 2.7-2 より、以下のことが確認できる。 ・障害が発生したアドレスは、0xc0168a18 ・参照しようとしたアドレスは、0x8f (3) 障害発生時の命令確認 障害発生時にどの命令が処理されていたかを確認するため、停止したアドレス付近の メモリ内容をアセンブリコードで表示させる逆アセンブラ dis コマンドを入力する。 alicia> dis 0xc0168a18 10 0xc0168a18 <sys_flock>: add %al,(%eax) 0xc0168a1a <sys_flock+2>: idiv %edi 0xc0168a1c <sys_flock+4>: (bad) 0xc0168a1d <sys_flock+5>: call *0x56(%edi) 0xc0168a20 <sys_flock+8>: push %ebx 0xc0168a21 <sys_flock+9>: push %edi 0xc0168a22 <sys_flock+10>: mov 0x18(%esp),%eax 0xc0168a26 <sys_flock+14>: mov 0x1c(%esp),%ebx 0xc0168a2a <sys_flock+18>: call 0xc0156d4d <fget> 0xc0168a2f <sys_flock+23>: test %eax,%eax 図 2.7-3 dis コマンドの出力メッセージ 図 2.7-3 より、障害が発生したアドレスでは、sys_flockルーチンの最初の命令addを実 行していることが確認できる。実行の内容は、 al + (eax) ⇒ al である。次に、AL レジスタ、EAX レジスタの内容がどのような値であったかを調べる ために、バックトレースを表示する bt コマンドを入力する。 btコマンドでは、図 2.7-4 のようにスタック情報を表示することができる。 alicia> bt PID: 3297 TASK: f7451930 CPU: 0 COMMAND: "perl" #0 [e87dee34] disk_dump at f89619f6 #1 [e87dee38] printk at c01219d3 #2 [e87dee44] freeze_other_cpus at f8961827 #3 [e87dee54] start_disk_dump at f89618d2 #4 [e87dee64] try_crashdump at c0133479 #5 [e87dee6c] die at c0106009 #6 [e87deea0] do_page_fault at c011a88c #7 [e87def80] error_code (via page_fault) at c02c7e45 EAX: 0000008f EBX: 00000003 ECX: 00000002 EDX: 0000007b - 2-106 - EBP: e87de000 DS: 007b ESI: 00000002 ES: 007b CS: 0060 EIP: c0168a18 ERR: ffffffff EDI: 093902f8 EFLAGS: 00010287 #8 [e87defbc] sys_flock at c0168a18 #9 [e87defc0] system_call at c02c7364 EAX: 0000008f EBX: 00000003 ECX: 00000002 EDX: 04598c0c DS: 007b ESI: 00000002 ES: EDI: 093902f8 SS: 007b ESP: bffe2cf8 EBP: bffe2d28 CS: 0073 EIP: 004737a2 ERR: 0000008f 007b EFLAGS: 00000282 alicia> 図 2.7-4 bt コマンドの出力メッセージ バックトレースから、EAX レジスタの値が 0x8f であることが判る。また、この 0x8f をアドレス情報としてそのメモリ内容を参照しようとしたところで、ページフォルト の障害が発生したことが判る。ページフォルトとは、CPU で実行中の命令によって メモリ上に存在しないページアドレスを参照することにより発生する障害で、ユーザ プロセス処理、カーネル処理のいずれでも発生しうる。ページフォルトそのものは異 常処理ではなく、正常な処理中にも発生するが、カーネルの処理中には発生しないよ うに設計されている。にもかかわらずカーネル処理中にページフォルトが発生した場 合には、不正なカーネル処理が行われたと判断し、カーネルは自身を停止させる。 次にEAXレジスタの値を元に、一連の処理が正しく実行されたと仮定して、カーネ ル処理を追っていく。sys_flockをコールしているのは、バックトレース#9 エントリ より、system_callであることが判る。system_callルーチンの逆アセンブラを表示さ せるため、disコマンドを入力する。(図 2.7-5) alicia> dis c02c7343 10 0xc02c7343 <system_call+11>: mov $0x7b,%edx 0xc02c7348 <system_call+16>: mov %edx,%ds 0xc02c734a <system_call+18>: mov %edx,%es 0xc02c734c <system_call+20>: mov $0xfffff000,%ebp 0xc02c7351 <system_call+25>: and %esp,%ebp 0xc02c7353 <system_call+27>: testb $0x81,0x8(%ebp) 0xc02c7357 <system_call+31>: jne 0xc02c73cc <syscall_trace_entry> 0xc02c7359 <system_call+33>: cmp $0x11d,%eax 0xc02c735e <system_call+38>: jae 0xc02c7408 <syscall_badsys> 0xc02c7364 <syscall_call>: call *0xc03159bc(,%eax,4) 0xc02c736b <syscall_call+7>: mov %eax,0x18(%esp,1) 図 2.7-5 dis コマンドの出力メッセージ - 2-107 - sys_flock をコールする部分のコードは、 call (0xc03159bc+EAX×4) となっている。ベースとなっている 0xc03159bcの内容を、rdコマンドを使って表示させ てみると、図 2.7-6 のように 4 バイトずつのアドレス情報が得られる。 alicia> rd c03159bc 152 c03159bc: c012bb41 c0123a5f c0104928 c01561dc A..._:..(I...a.. c03159cc: c015623e c01557fd c01558ef c0124d15 >b...W...X...M.. (途中 略) c0315bcc: c012e0e4 c01550ec c0159fd1 c016d8af .....P.......... c0315bdc: c0121156 c012cc15 c0134708 c013471f V........G...G.. c0315bec: c0155dc7 c0165e05 c0166504 c0168a18 .]...^...e...... c0315bfc: c014d655 c015661f c0156681 c012e15d U....f...f..]... c0315c0c: c0157567 c0126654 c014a01d c014a113 gu..Tf.......... alicia> 図 2.7-6 rd コマンドの出力メッセージ EAX レジスタの値が 0x8f の場合のアドレス 0xc03159bc + 0x8f × 4 = 0xc0315bf8 を調べてみると、sys_flock ルーチンのアドレス(0xc0168a18)を示している。このこ とから、このアドレス領域は、各システムコールの処理ルーチンのアドレステーブル であると仮定することができる。 カーネルのソースコードを調べてみると、0x8fはsys_flockのシステムコールIDであり、 このルーチン(sys_flock)では、EAXレジスタが、システムコールIDで使用されている ことが判る。次にシステムコールIDを定義している /usr/include/asm/unistd.hを 図 2.7-7 に示す。0x8fは、10 進で 143 である。 #define _ASM_I386_UNISTD_H_ /* * This file contains the system call numbers. */ #define __NR_restart_syscall 0 #define __NR_exit 1 #define __NR_fork 2 #define __NR_read 3 - 2-108 - (途中 略) #define __NR__llseek 140 #define __NR_getdents 141 #define __NR__newselect 142 #define __NR_flock 143 #define __NR_msync 144 #define __NR_readv 145 #define __NR_writev 146 #define __NR_getsid 147 #define __NR_fdatasync 148 (途中 略) 図 2.7-7 /usr/include/asm/unistd.h の内容 ここまでの解析で、sys_flockがコールされるまでの処理で、EAXレジスタの使われ 方に特に異常がないことが判った。sys_flockルーチンでadd命令が実行されて障害が 発生したのかを、レジスタの値以外の観点から調べることにし、add命令が実行され た過程を調査していく。まずは、ダンプ上のコードを表示させるために、rdコマンド で使用する。 (図 2.7-8) alicia> rd sys_flock 10 c0168a18: fff70000 5657ffff 448b5753 5c8b1824 ......WVSW.D$..\ c0168a28: 1ee81c24 85fffee3 0fc789c0 0000f084 $............... c0168a38: c1de8900 e38302ee ........ alicia> 図 2.7-8 sys_flock ルーチンのダンプ上のコード (4) 逆アセンブルリスト 追求を進めていく上でまず確認することは、ダンプ上の該当アドレスのメモリ内容と カーネルコードが一致していることを確認することである。これは、デバック情報付き でコンパイルしたカーネルの逆アセンブルリスト(図 2.7-9)と、ダンプのメモリ内容 を比較することで確認できる。 # objdump -S /usr/src/linux-2.6.9-11ELsmp-devmem/vmlinux | grep -A 5 "c0168a18 " c0168a18 <sys_flock>: c0168a18: 55 push %ebp c0168a19: bd f7 ff ff ff mov $0xfffffff7,%ebp c0168a1e: 57 push %edi - 2-109 - c0168a1f: 56 push %esi c0168a20: 53 push %ebx # objdump -s /usr/src/linux-2.6.9-11ELsmp-devmem/vmlinux | grep -A 5 c0168a10 c0168a10 4089f85b 5e5f5dc3 55bdf7ff ffff5756 @..[^_].U.....WV c0168a20 53578b44 24188b5c 241ce81e e3feff85 SW.D$..\$....... c0168a30 c089c70f 84f00000 0089dec1 ee0283e3 ................ c0168a40 fb83f601 83e60183 fb08740f f6c32075 ..........t... u c0168a50 0af6401c 030f84c7 00000089 d989e289 ..@............. c0168a60 f8e8e7e5 ffff85c0 89c50f85 b2000000 ................ 図 2.7-9 カーネルの逆アセンブルリスト ここで、大きな異変に気付く。ダンプ上のアドレス 0xc0168a18 の内容がカーネルを アセンブルした時に得られる内容と食い違っていることである。これは、図 2.7-3/図 2.7-8/図 2.7-9 を比較することで確認できる。 図 2.7-10 にアドレス 0xc0168a18 の内容を比較して表示してみた。ダンプ上(Aliciaに よる表示)では、下位 16 ビットが 0 に変更されていることが判る。本来は、0xfff7bd55 であったはずである。図 2.7-10 の矢印で示したように、Aliciaの表示とobjdumpの表示 では、byte単位での表示(方向)が異なることに注意する必要がある。 alicia> rd sys_flock c0168a18: fff70000 5657ffff 448b5753 5c8b1824 ......WVSW.D$..\ # objdump -s c0168a10 55bdf7ff ffff5756 U.....WV 図 2.7-10 Alicia と objdump の表示方向の違い (5) 原因特定 ここまでの解析から、何らかの理由により、アドレス 0xc0158a18 の内容が 2 バイ ト分変更され、sys_flock ルーチンで誤ったコードが実行されてしまい、その結果、 ページフォルト障害が発生したものと判断できる。 メモリ内容が書き換えられた理由としては、 ・ メモリハードウェア障害 ・ カーネルのバグにより、意図しないアドレスに書き込みを行っている などが考えられる。 最終的な原因判明は、本障害がハードウェア障害によるものなのか、カーネルのバグ - 2-110 - によるものなのかを明らかにすることである。そのためには、メモリ障害の痕跡を各種 ログで調査し、あるいは、カーネルロジックとつきあわせながら更に詳細なダンプ追求 を実施する。一般的には、ハードウェアによる問題かソフトウェアによる問題かの切り 分けは、何らかの痕跡(状況証拠)を元に追求の初期段階で判断をくだす必要がある。 追求に長時間を要す場合には、トラブルに関連するハードウェア部位に対してひとまず 部品を交換し、再発に備えるといったケースも少なくない。 2.7.1.4 対策 メモリハードウェア障害が疑わしい場合、または、メモリハードウェア障害と判断 できた場合には、メモリチェックユーティリティにより、メモリに障害がないかを調 べ、メモリのハードウェア交換を行う。 - 2-111 - 2.8 ネットワーク障害 2.8.1 障害概要 事例として取り上げる障害の内容について以下に述べる。 表 2.8-1 ネットワーク障害概要 番号 2.8.1 発生日 2005/xx/xx 解決日 2005/xx/xx 現象 Bonding 構成が組まれた環境において、ネットワークインターフェースのリンクダ ウンが発生する。 分類 ネットワーク障害 発生環境 OS Turbolinux 10 Server CPU Pentium 4 3.20GHz x 1 メモリ 256Mbyte ハードディスク IDE 120Gbyte ネットワーク Intel Corp. 82557/8/9 Ethernet Pro 100 x 2 原因 ケーブルの断線によるリンクダウンが発生 対策 ネットワークケーブルの交換 解析手法 Swatch による silo 監視から、障害内容を確認 2.8.2 障害検知 通常運用中に、swatch 監視より、”Messages from Swatch”という件名のメールが送信さ れる。送信された内容を確認する。 Sep 1 14:33:44 enfuzion01 kernel: bonding: bond0: link status definitely down for interface eth1, disabling it Sep 1 14:33:44 enfuzion01 kernel: bcm5700: eth1 NIC Link is Down 図 2.8-1 Message from Swatch メッセージの内容は、”eth1 のリンクがダウンした”、というものである。これを踏まえて、 ksysguardにて、ネットワークの転送状態を確認することにする。図 2.8-2 障害発生中の ksysguardを見てわかるとおり、パケットの送受信数が”0”であることを示していることが わかる。推測できることは、パケットが送受信できていない = ネットワークインターフェ ースに何らかの問題が発生したことがわかる。 - 2-112 - 送受信の転送パケット数が、”0”という事は eth1 で、 障害が発生したと判断して良い。 図 2.8-2 障害発生中の ksysguard 表 2.8-2 ksysguard の図内構成 パケット データ エラー ドロップされた パケット Local Host Remote Host bond0 受信 bond0 受信 bond0 受信 bond0 受信 bond0 送信 bond0 送信 bond0 送信 bond0 送信 eth0 受信 eth0 受信 eth0 受信 eth0 受信 eth0 送信 eth0 送信 eth0 送信 eth0 送信 eth1 受信 eth1 受信 eth1 受信 eth1 受信 eth1 送信 eth1 送信 eth1 送信 eth1 送信 bond0 受信 bond0 受信 bond0 受信 bond0 受信 bond0 送信 bond0 送信 bond0 送信 bond0 送信 eth0 受信 eth0 受信 eth0 受信 eth0 受信 eth0 送信 eth0 送信 eth0 送信 eth0 送信 eth1 受信 eth1 受信 eth1 受信 eth1 受信 eth1 送信 eth1 送信 eth1 送信 eth1 送信 2.8.3 障害切り分け NIC のドライバが稼動しているか確認を行なう。これは、ifconfig コマンドを使用するこ - 2-113 - とで判明する。判断する内容として、下線が引かれている、UP, RUNNING というキーワ ードが出ている事を確認する。 「UP」は現在正常に稼働していることを示し、 「RUNNING」 はドライバが正常にロードされている状態を示す。 bond0 Link encap:Ethernet HWaddr 00:12:3F:6E:75:9E inet addr:172.16.37.141 Bcast:172.16.39.255 UP BROADCAST RUNNING MASTER MULTICAST Mask:255.255.252.0 MTU:1500 Metric:1 RX packets:2773525 errors:0 dropped:0 overruns:0 frame:0 TX packets:1101416 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1979358842 (1887.6 Mb) eth0 Link encap:Ethernet TX bytes:72928144 (69.5 Mb) HWaddr 00:12:3F:6E:75:9E UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:582716 errors:0 dropped:0 overruns:0 frame:0 TX packets:550715 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:282233562 (269.1 Mb) TX bytes:38724565 (36.9 Mb) Interrupt:18 Memory:dfcf0000-dfd00000 eth1 Link encap:Ethernet HWaddr 00:12:3F:6E:75:9E UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:2190809 errors:0 dropped:0 overruns:0 frame:0 TX packets:550701 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1697125280 (1618.5 Mb) lo TX bytes:34203579 (32.6 Mb) Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:4431 errors:0 dropped:0 overruns:0 frame:0 TX packets:4431 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:382582 (373.6 Kb) TX bytes:382582 (373.6 Kb) 図 2.8-3 障害発生時の ifconfig 結果 この結果から、インターフェースは稼動していると判断できるが、ifconfig コマンドの結果 からは、ネットワークデバイスドライバは、正常に稼動している、という事しかわからな い。ハードウェア障害なのか、ソフトウェア障害なのかを切り分ける為に、H/W の状態を ethtool にて取得する。 - 2-114 - 表 2.8-3 障害発生後の ethtool による H/W 状況の収集 # ethtool eth0 # ethtool eth1 Settings for eth0: Settings for eth1: Supported ports: [ TP MII ] Supported ports: [ TP MII ] Supported link modes: Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full Supports auto-negotiation: Yes Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 100baseT/Half 100baseT/Full Advertised auto-negotiation: Yes Advertised auto-negotiation: Yes Speed: 10Mb/s Speed: 10Mb/s Duplex: Half Duplex: Half Port: MII Port: MII PHYAD: 1 PHYAD: 1 Transceiver: internal Transceiver: internal Auto-negotiation: on Auto-negotiation: on Supports Wake-on: g Supports Wake-on: g Wake-on: d Wake-on: d Current message level: 0x00000007 (7) Current message level: 0x00000007 (7) Link detected: yes Link detected: no 実行結果から、eth1 の Link detected が”No”になっていることがわかった。これは物理的 に電気信号が切断された場合に発生する状態である。”Message from Swatch”の内容と併せ ると、ハードウェア的に接続がダウンしたと判断できる。このことから、物理的な結線に 問題があると考えられ、ネットワークハブの FC/COL ランプを確認したら、動作ランプが 消えていることが確認できた。 2.8.4 障害回復手順 ケーブルには、外傷は見つからないので、内部断線していると思われる為、ケーブルチ ェッカーによる診断を行なう。(無い場合は、直接、新品ケーブルへ交換してみる)確認した ところ、内部断線を起こしている事が判明したので、新品のケーブルに入替え、Link ラン プが点灯し、ksysguard にてパケットの転送が再開されていることの確認を行なう。問題 発生時、”0”と表示されていた項目も”0”以外の数値が表示されており、通信が再開されてい ることがわかる。本当に回復したのか確認するために、syslog の内容を確認し、eth1 が Linkup していることを確認する。 # tail –f /var/log/messages | grep up Aug 19 12:41:13 enfuzion01 kernel: e100: eth1: e100_watchdog: link up, 100Mbps, full-duplex 図 2.8-4 回復後の syslog 内容(抜粋) - 2-115 - ログ上、インターフェースが up しているという事から、H/W 監視を行う事ができる ethtool にて、Link detected が yes になっていることを確認する。 表 2.8-4 回復後の ethtool の結果 # ethtool eth0 # ethtool eth1 Settings for eth0: Settings for eth1: Supported ports: [ TP MII ] Supported ports: [ TP MII ] Supported link modes: Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full Supports auto-negotiation: Yes Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Half 100baseT/Full 100baseT/Full Advertised auto-negotiation: Yes Advertised auto-negotiation: Yes Speed: 10Mb/s Speed: 10Mb/s Duplex: Half Duplex: Half Port: MII Port: MII PHYAD: 1 PHYAD: 1 Transceiver: internal Transceiver: internal Auto-negotiation: on Auto-negotiation: on Supports Wake-on: g Supports Wake-on: g Wake-on: d Wake-on: d Current message level: 0x00000007 (7) Current message level: 0x00000007 (7) Link detected: yes Link detected: yes 問題を回避できたと判断し、tcpdump、ping による疎通確認を行なう。 tcpdump による通信確認を行なう。tcpdump とはネットワーク通信の状態を見ることがで きるツールである。tcpdump で表示される内容をログファイルに書き込み、別コンソール から結果内容を抽出する方法で結果を見る事にする。tcpdump の内容は非常に膨大な量の データが流れる為、ファイルに吐き出し、必要な情報だけを抽出することができる。 # tcpdump > tcpdump.log 図 2.8-5 tcpdump の開始 tcpdump 開始の後、別コンソールにて、対向 PC(dhcp-148)に対して ping 実行する。書き 出されているログに対して、grep 検索を行い、ログの抽出を行なう。 # ping –c 3 dhcp-148 図 2.8-6 ping の実行 ping を実行することで、通信した結果が、tcpdump のログに残る。 # tail –f tcpdump.log | grep dhcp-148 - 2-116 - 11:24:58.366899 arp reply dhcp-148 is-at 00:90:99:16:5f:9a 11:24:58.366912 IP enfuzion01 > dhcp-148: icmp 64: echo request seq 1 11:24:58.367047 IP dhcp-148 > enfuzion01: icmp 64: echo reply seq 1 11:24:59.367494 IP enfuzion01 > dhcp-148: icmp 64: echo request seq 2 11:24:59.367605 IP dhcp-148 > enfuzion01: icmp 64: echo reply seq 2 11:25:00.368141 IP enfuzion01 > dhcp-148: icmp 64: echo request seq 3 11:25:00.368279 IP dhcp-148 > enfuzion01: icmp 64: echo reply seq 3 図 2.8-7 tcpdump 結果 疎通できている場合、対向 PC より reply が送信されていることがわかる。この結果から、 TCP/IP による疎通ができていることがわかる。 traceroute コマンドにて、障害発生前と同じ経路で通信が行なえているか確認を行なう。 障害前と同じ経路であれば、障害前の状態に戻せたと判断できる。 続いて、traceroute による経路確認を行なう。 # traceroute www.ipa.go.jp traceroute to www.ipa.go.jp (xxx.xxx.xxx.xxx), 30 hops max, 38 byte packets 1 ns (172.xx.xxx.xxx) 2 gw18-2.hoge-hoge.net (xxx.xxx.xxx.xxx) 3 x20-1.hoge-hoge.net (xxx.xxx.xxx.xxx) 4 gw148.hogehog.hoge.net (xxx.xxx.xxx.xxx) 11.833 ms 5 gw254.hogehog.hoge.net (xxx.xxx.xxx.xxx) 8.905 ms 6 hoge.hoge.net (xxx.xxx.xxx.xxx) 7 xxx.hogehoge.net (xxx.xxx.xxx.xxx) 8 xxx.hogehoge.hogehoge.net (xxx.xxx.xxx.xxx) 9 hoge.hoge.hoge.hoge.hogehoge.net (xxx.xxx.xxx.xxx) 10 0.225 ms 0.152 ms 0.276 ms 11.129 ms 0.770 ms 20.743 ms xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx) 0.723 ms 0.704 ms 8.910 ms 1.063 ms 8.921 ms 10.330 ms 10.361 ms 10.403 ms 20.694 ms 66.105 ms 0.687 ms 0.993 ms 10.175 ms 10.422 ms 0.658 ms 20.833 ms 10.735 ms 46.977 ms 20.748 ms 10.856 ms 10.770 ms 48.357 ms 図 2.8-8 回復後の traceroute 情報 復旧後の確認として ksysguard にてパケットの転送状態を確認する。結果、eth1 の送受信 が、”0”という表示ではない事が確認できる。 - 2-117 - 表示が、”0”ではないので、通信が行なわれていると 判断して良い。 図 2.8-9 復旧後の ksysguard - 2-118 - 2.9 ディスク障害 2.9.1 H/W RAID 5/1 障害発生時、警告音が鳴り、監視ツールより、指定したユーザ宛てに通知され、その結 果から、障害問題の切り分けをし、障害発生後の回復手順についても検証する。RAID5,1 とも同じ手順である。 2.9.1.1 障害概要 事例として取り上げる障害の内容について以下に述べる。 表 2.9-1 ハードウェア RAID 障害概要 番号 2.9.1 現象 H/W RAID 環境にて Channel ID2 への I/O が行なえない。 分類 ディスク障害/ ディスク不良 発生環境 OS Turbolinux 10 Server CPU Athlon64 3500+ メモリ 1Gbyte ハードディスク SCSI 36GB x 2 ~ 3 ネットワーク TL-8139/8139C/8139C+ 発生日 2005/xx/xx 解決日 原因 Channel ID2 にて、I/O 障害が発生 対策 不良ディスクの交換 解析手法 Storage Manager*からの警告および syslog の内容を確認 2005/xx/xx *Storage Manager は、Adaptec 社製 HostRAID,SCSI デバイスを監視できる GUI ツール である。 2.9.1.2 障害検知 障害時、RAID カードよりアラート音が発せられ、監視ツールからルートユーザ宛てにメ ールで障害発生通知(Event notification – Event Type: Error)が送信される。RAID カード から発せられるアラート音は、問題が解決されるまで鳴り続ける。(オプションでアラート OFF もある)。 # tail –f /var/log/messages Sep 23 12:19:19 rouge login(pam_unix)[1400]: session opened for user root by (uid=0) Sep 23 12:19:47 rouge kernel: SCSI device sda: 143237120 512-byte hdwr sectors (73337 MB) Sep 23 12:19:47 rouge kernel: sda: Write Protect is off Sep 23 12:19:47 rouge kernel: SCSI device sda: drive cache: write through - 2-119 - 図 2.9-1 障害発生直後の syslog 情報 This message was generated by the Adaptec Storage Manager Agent. Please do not reply to this message. Event Description: Verify failed: controller 1, logical device 1 ("array01raid5") [0x00] Event Type: Error Event Source: rouge Date: 09/21/2005 Time: 21:23:20 PM JST 図 2.9-2 Storage Manager からのメール(抜粋) 2.9.1.3 障害切り分け この情報により、RAID 構成の”device1”にて障害が発生したことがわかり、Storage Manager にて、状態を確認したところ、Channel ID2 が消えていることが判る。 この場合、 Channel ID2 が表示されているのが、正常動作で あるが、障害発生時には表示されていない。 図 2.9-3 障害発生の Storage Manager - 2-120 - 2.9.1.4 障害解析 Storage Manager から送信されたメッセージ中(図 2.9-2)に、”Veryfiy faild: Controller 1 ~”と書かれていた。内容を確認すると、logicaldevice(アレイ構成)に障害が発生したこと を意味するメッセージであり、Storage Manager 上で、状態を確認すると、3 つあるディ スクイメージが、2 つになっていることが分かる。これに合わせて、図 2.9-2” Storage Manager からのメール(抜粋)”のメールと同時刻に、図 2.9-4”Event Notification - Event Type: Informational”という件名のメールが送られてくる。このメールには、障害が発生 している device が書かれている。 This message was generated by the Adaptec Storage Manager Agent. Please do not reply to this message. Event Description: Physical drive removed: controller 1, channel 0, SCSI device ID 2 Event Type: Informational Event Source: dhcp-148 Date: 08/25/2005 Time: 07:19:59 PM JST 図 2.9-4 Event Notification - Event Type: Informational この 2 つの情報から、logicaldevice1の SCSI Channel ID2 で物理的な障害が発生したこ とがわかる。これによりディスク交換が必要と判断できる。 2.9.1.5 障害回復手順 SCSI RAID カードには、自動再構成の機能が含まれているため、新品ディスクに換える 事で再構成が自動で開始される。この際、fdisk は行なわなくて良い。図 2.9-5“再構成中の Storage Manager”は再構成中の画面情報である。ChannelID 2 に障害が発生し、障害復旧 に伴う再構成が行われている事が視覚的にわかるようになっている。 - 2-121 - 図 2.9-5 再構成中の Storage Manager 最後に、df コマンドにて、全てのファイルシステムを表示し、回復したことを確認する。 # df -a Filesystem 1K-blocks /dev/sda1 10317828 5043352 4750360 none 0 0 0 - /proc usbfs 0 0 0 - /proc/bus/usb sysfs 0 0 0 - /sys 10317860 32936 9760804 0 0 0 /dev/sda3 none Used Available Use% Mounted on - 2-122 - 52% / 1% /home - /dev/pts 2.9.2 S/W RAID5/1 障害発生時、監視ツールより、指定したユーザ宛てにメールにて通知され、その結果か ら、障害問題の切り分けをし、障害発生後の回復手順についても検証する。RAID5,1 とも 同じ手順である。 2.9.2.1 障害概要 事例として取り上げる障害の内容について以下に述べる。 表 2.9-2 ソフトウェア RAID 障害概要 番号 2.9.2 現象 S/W RAID 環境にて、/dev/hdb への I/O が行なえない。 分類 ディスク障害/ ディスク不良 発生環境 OS Turbolinux 10 Server CPU Athlon64 3500+ メモリ 1Gbyte ハードディスク IDE 80Gbyte x 2 ~ 3 ネットワーク TL-8139/8139C/8139C+ 発生日 2005/xx/xx 原因 /dev/hdb にて、I/O 障害が発生 対策 不良ディスクの交換 解析手法 swatch による syslog 監視から、障害内容を確認 解決日 2005/xx/xx 2.9.2.2 障害検知 障害発生時、swatch 監視より設定したユーザ宛てにメールで障害発生通知が行われる。 送付内容は以下の通り。 Sep 2 04:02:16 dhcp-148 kernel: end_request: I/O error, dev hdb, sector 41929433 Sep 2 04:02:16 dhcp-148 kernel: md: write_disk_sb failed for device hdb2 図 2.9-6 Message from Swatch このメッセージから読み取れることは、/dev/hdb のディスクに問題が発生した、というこ とである。 2.9.2.3 障害切り分け システムよりディスク障害の警告メールが送られてきたので、状態確認のため、mdadm にて状況確認を行なうことにする。 - 2-123 - # mdadm -Q --detail /dev/md1 /dev/md1: Version : 00.90.01 Creation Time : Tue Aug 30 15:25:29 2005 Raid Level : raid5 Array Size : 20964608 (19.99 GiB 21.47 GB) Device Size : 10482304 (10.00 GiB 10.73 GB) Raid Devices : 3 Total Devices : 3 Preferred Minor : 1 Persistence : Superblock is persistent Update Time : Wed Aug 31 12:11:32 2005 State : clean, degraded Active Devices : 2 Working Devices : 2 Failed Devices : 1 Spare Devices : 0 Layout : left-asymmetric Chunk Size : 64K UUID : 763b126d:630c5e2e:61149fcb:fad9c28e Events : 0.153 Number Major Minor RaidDevice State 0 3 3 0 active sync 1 0 0 - removed 2 22 66 2 active sync 3 3 66 - faulty /dev/hda3 /dev/hdd2 /dev/hdb2 図 2.9-7 S/W RAID 状況確認 2.9.2.4 障害解析 図 2.9-7 より、md1 の/dev/hdbがRAID構成から外れている事がわかる。このことを踏ま えて、syslogを確認(図 2.9-8)し、/dev/hdbにて何が発生していたかを確認する。I/Oエラ ーが発生しているが、fsckによるディスクの復旧を行い、改善されない場合、ディスクへの 書き込みが出来なくなっているので、ディスク不良と判断しディスク交換することになる。 # less /var/log/messages - 2-124 - Jul 5 21:40:51 usen4 kernel: end_request: I/O error, dev 16:41 (hdb),sector 34425168 Jul 5 21:40:56 usen4 kernel: hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error } Jul 5 21:40:56 usen4 kernel: hdb: dma_intr: error=0x40 {UncorrectableError }, LBAsect=33262669, ector=33262544 図 2.9-8 syslog 2.9.2.5 障害回復手順 シングルユーザモードに移行した後、fsck による復旧を試みる。 # shutdown –F now 図 2.9-9 シングルユーザモードへの移行 移行終了の後、fsck によるディスク修復を試みる。 # fsck –c –y /dev/md1 図 2.9-10 fsck の実行 結果として、fsck を実行したが障害を取り除くことができなかった。新品ディスクに交換 する以外に術が無いことが判明した。S/W RAID 構成の回復方法は、raidhotadd コマンド による再構成にて RAID 構成を元に戻すことができる。ただし、S/W RAID 構成が解除さ れた場合、システムを一時停止することが必要となる点に注意が必要である。これは、稼 動中にディスクを入れ換えてもシステムは認識できないためである。新品のディスクをそ のままマウントしただけでは、S/W RAID の再構成は行なえない。再構成を行う為に fdisk によるパーティションの再設定が必要であり、前準備として図 2.9-11 の再構成コマンドを 実行する必要がある。 # raidhotadd /dev/md0 /dev/hdb2 # raidhotadd /dev/md1 /dev/hdb2 図 2.9-11 raidhotadd による再構成コマンド 再構成中の進捗状況は、/proc/mdstat を見ることで、確認できる。下線が引いてある情報 が進行状況を知らせるものになる。 # cat /proc/mdstat Personalities : [raid5] md1 : active raid5 hda3[0] hdd2[2] 20964608 blocks level 5, 64k chunk, algorithm 0 [3/2] [U_U] - 2-125 - md0 : active raid5 hdb1[3] hda2[0] hdd1[2] 20964608 blocks level 5, 64k chunk, algorithm 0 [3/2] [U_U] [>....................] recovery = 1.0% (113280/10482304) finish=12.2min speed=14160K/sec unused devices: <none> 図 2.9-12 S/W RAID 再構成進行状態 S/W RAID の再構成(raidhotadd コマンド)の複数同時実行はできないが、投下されたコマ ンドは、前者の再構成が終了した後、すぐに後者の再構成が開始される。/proc/mdstat に て、構成が完了した事が確認できたら、mdstat にて、構成が復元できたかを確認する。 # less /proc/mdstat Personalities : [raid5] md1 : active raid5 hdb2[1] hda3[0] hdd2[2] 20964608 blocks level 5, 64k chunk, algorithm 0 [3/3] [UUU] md0 : active raid5 hdb1[1] hda2[0] hdd1[2] 20964608 blocks level 5, 64k chunk, algorithm 0 [3/3] [UUU] 図 2.9-13 mdstat 結果 - 2-126 - 2.9.3 LVM LVM はカーネル 2.4 からサポートされたディスク管理機能である。カーネル 2.6 にて根 本的な見直しが行なわれ LVM2 へとバージョンアップされている。この LVM を利用する と複数のハードディスクをグループ化し 1 つの論理ディスクとして運用することも出来る。 スナップショット、構成変更を利用し、障害回避する手段を検証する。 2.9.3.1 障害概要 事例として取り上げる障害の内容について以下に述べる。 表 2.9-3 LVM 障害事例 番号 2.9.3 発生日 2005/xx/xx 現象 /dev/hdb への I/O が行えない。 分類 ディスク障害/ ディスク不良 発生環境 OS Turbolinux 10 Server CPU Athlon64 3500+ メモリ 1Gbyte ハードディスク IDE 80Gbyte x 2 ネットワーク TL-8139/8139C/8139C+ 原因 /dev/hdb にて、I/O 障害が発生 対策 不良ディスクの交換 解析手法 Swatch による syslog 監視から、障害内容を確認 解決日 2005/xx/xx 2.9.3.2 障害検知 障害発生時、swatch 監視より設定したユーザ宛てにメールで障害発生通知が行われる。 送付内容は以下の通り。 Sep 3 04:03:15 dhcp-148 kernel: end_request: I/O error, dev hdb, sector 41929433 Sep 3 04:03:15 dhcp-148 kernel: md: write_disk_sb failed for device hdb2 図 2.9-14 Message from Swatch 2.9.3.3 障害切り分け このメッセージから読み取れることは、hdb のディスクに問題が発生した、ということ である。同時刻に syslog にて、どのようなメッセージが出ているかも確認する必要がある。 Sep 8 11:49:56 dhcp-148 kernel: ide0: reset timed-out, status=0x80 Sep 8 11:49:56 dhcp-148 kernel: end_request: I/O error, dev hdb, sector 4575 Sep 8 11:49:56 dhcp-148 kernel: EXT3-fs error (device dm-0): ext3_readdir: directory #2 contains a hole at offset 0 Sep 8 11:49:56 dhcp-148 kernel: Aborting journal on device dm-0. - 2-127 - Sep 8 11:49:56 dhcp-148 kernel: end_request: I/O error, dev hdb, sector 447 Sep 8 11:49:56 dhcp-148 kernel: Buffer I/O error on device dm-0, logical block 0 Sep 8 11:49:56 dhcp-148 kernel: lost page write due to I/O error on dm-0 Sep 8 11:49:56 dhcp-148 kernel: ext3_abort called. Sep 8 11:49:56 dhcp-148 kernel: EXT3-fs error (device dm-0): ext3_journal_start: Detected aborted journal 図 2.9-15 syslog syslog を確認したところ、I/O エラーを表示していることから、ディスク不良が発生してい るようである。 2.9.3.4 障害解析 マウントされている LVM の領域へ移動し、アクセスできるかを確認したところ、アクセ スできない状態になっていた。この状態では何もできないため、シングルユーザモードに 移行し、fsck による回復処置を試みる。 # shutdown –F now 図 2.9-16 シングルユーザモードへ移行 シングルユーザモードに移行終了の後、fsck を実行し回復を試みる。 # fsck –c –y /dev/hdb2 図 2.9-17 fsck の実行 fsck を実行しディスクの復旧後、システムを再起動し、LVM の領域をマウントしようとし ても、マウントは出来なかった。これにより、新品ディスクへ交換する以外、術がないこ とが判明した。 2.9.3.5 障害回復手順 新品ディスクに入換えても、システム上、LVM の構成情報は/etc/lvm ディレクトリに存 在している。再構成を行おうとしても、旧構成情報が残っている為、pvcreate、lvcreate などの LVM 環境の再構成を行うコマンドを実行しても再構築が行なえない点に注意する。 ディスクを入れ換えた直後に、LVM の構成が行えない状況であっても lvdisplay、pvdisplay などの構成情報参照コマンドは、障害発生前の情報を返してしまう。これは構成情報が残 っているからである。しかし、この状況においても、lvremove,vgremove 等のコマンドは 使用できるので、以前作成した LVM 構成を削除した後に、環境を作り直すことになる。 (構 成手順は 3 章を参照) - 2-128 - 2.9.3.6 スナップショットを利用した障害回避法について LVM には、RAID のような補完機能は実装されていない為、ディスク障害が発生した場 合、自己修復によるデータの復旧が出来ない点が問題となる。この問題を補う為には日常 的なバックアップを行う必要がある。LVM は、システムの運用中にボリューム単位で別の 空き領域に対してバックアップを行うことができるスナップショット機能を実装している。 スナップショットは、ある時点のイメージを別領域へコピーする機能である。コピーされ た情報を、共有ディスク(例:NFS サーバなど) へ移すことにより、システム/サービスを停 めずバックアップを行う事が出来る。これは大きなメリットである。この処理を、定期的 に実施し続けることで、障害発生時の復旧に有効な手法となる。LVM 環境、スナップショ ットの作成方法については、3 章に記す。 スナップショットで収集されたデータは、名が示すとおり断片的なデータでしかないた め、スナップショットで採られたデータは、マウントし別の領域へコピーする必要がある。 コピー終了後は、マウントを解除し、スナップショットも削除する。これは、次回のスナ ップショットを行う為の準備でもある。以下にサンプルスクリプトを添付する。サンプル スクリプトでは、NFS サーバに対してバックアップを行うようにしている。 #!/bin/sh # PARTITION=(lv01) PREFIX=/dev/vg_01 SNAP_SIZE=4098M SNAP_NAME=snap0 BACKUP_DIR=backup.exsample.com:/export MOUNT_POINT=/mnt/backup MOUNT_SNAP=/mnt/snap echo nfs mount start. mount $BACKUP_DIR $MOUNT_POINT || exit echo nfs mount end.for i in ${PARTITION[*]} do lvremove -f ${PREFIX}/${SNAP_NAME} lvcreate --snapshot --size $SNAP_SIZE --name $SNAP_NAME ${PREFIX}/$i mount ${PREFIX}/$i ${MOUNT_SNAP} cp ${MOUNT_SNAP}/* ${MOUNT_POINT} umount ${PREFIX}/$i ${MOUNT_SNAP} lvremove -f ${PREFIX}/${SNAP_NAME} done umount $MOUNT_POINT 図 2.9-18 スナップショットを使用するサンプルスクリプト - 2-129 - 2.9.3.7 ディスク使用量増大に対する対処について LVM でボリュームを管理する最大のメリットは、ディスクの空き容量が少なくなったとき、 新しいハードディスクを追加し、容易にロジカルボリュームのサイズを拡張できるところ にある。構築手順については、3 章に記す。 - 2-130 - 3 ツール評価 3.1 パフォーマンス監視ツールの信頼性評価 本節では、パフォーマンス監視ツールとして sar、iostat、mpstat という 3 つのコマンド の信頼性評価を行う。特に高負荷時におけるこれらのツールの挙動を調べ、データが指定 した間隔で取得できないという既知の問題に対していくつかの回避策を提示する。 3.1.1 ツールの概要 sar、iostat、mpstat は一定ごとにカーネルが提供する様々なシステム統計情報を取得す ることにより、システムの負荷状況をモニタリングすることができるコマンドである。こ れらのコマンドは Linux システムでは sysstat というパッケージに含まれ、多くの Linux ディストリビューションでは標準で提供されている一般的なツールである。 3.1.1.1 sar sar は CPU 利用率、ネットワーク、ディスク I/O およびページングなどの多岐にわたる システム統計情報を一定間隔ごとに取得するコマンドである。取得した統計情報は標準出 力に出力されるが、”-o”オプションを使用することにより指定したファイルにバイナリ形式 で保存することもできる。バイナリ形式で保存した場合、統計情報を確認するには同コマ ンドを使用してテキスト形式に変換・出力する必要があるが、必要な情報を柔軟に取得す ることができる。 以下の 図 3.1-1 にsarコマンドでデータを取得し、結果をバイナリファイルとして保存す る方法を示す。 $ sar -A -o output_file 5 600 & モニタリングの開始 シ ス テ ム 統 計 情 報 を 5 秒 間 隔 で 600 回 取 得 し 、 output_file にバイナリデータとして保存 -A:取得可能な統計情報をすべて取得 -o:バイナリ形式として保存するファイル名を指定 $ killall sar モニタリングの終了 $ killall sadc 図 3.1-1 sar コマンドによるデータ取得手順例 図 3.1-1 で取得したファイルはバイナリ形式なので取得したデータを参照するにはsarコマ ンドでテキスト形式に変換する必要がある。図 3.1-2 に例としてCPU利用率のデータを取 得する方法を示す。 $ sar -u -f output_file 図 3.1-1 の sar コマンドで保存された統計情報 をテキストフォーマットに整形して出力する Linux 2.6.9-5.25AX (TAMA09) 09/06/05 -u:CPU 利用率を表示 -f:保存ファイル名を指定 - 3-1 - 22:50:07 CPU %user %nice %system %iowait %idle 22:50:12 all 32.26 0.00 0.00 1.00 66.73 22:50:17 all 99.80 0.00 0.20 0.00 0.00 22:50:22 all 100.00 0.00 0.00 0.00 0.00 22:50:27 all 100.00 0.00 0.00 0.00 0.00 22:50:32 all 100.00 0.00 0.00 0.00 0.00 22:50:37 all 99.80 0.00 0.20 0.00 0.00 (以下略) 図 3.1-2 sar による取得データの表示例 図 3.1-2 では-uオプションでCPU利用率を取得しているが、他にも-bオプションでディ スクI/Oに関する統計情報、-nオプションでネットワークに関する統計情報が取得できる。 その他のデータ取得に関してはsarのmanページを参照のこと。 3.1.1.2 iostat iostatは一定期間毎のディスクの転送回数や転送量、入出力リクエストキューの長さなど、 デバイスやパーティションごとの入出力の情報を取得するコマンドである(sarでも入出力 の情報は得られるが、システム全体の情報しか得られない)。取得された統計情報は標準出 力にテキスト形式で出力され、データをファイルに保存するためにはファイルリダイレク トを使用する必要がある。図 3.1-3 にiostatでデータを取得する方法を示す。 $ iostat –t -x 5 100 > output_file & モニタリングの開始 システム統計情報を 5 秒間隔で 600 回取得し、output_file にテキストデータとして保存 -t:データを取得した時刻を出力 -x:デバイスごとの統計情報を出力 モニタリングの終了 $ killall iostat 図 3.1-3 iostat によるデータ取得手順例 図 3.1-3 で取得したデータはテキスト形式で保存されているので 図 3.1-4 のようにcatコマ ンドなどで確認することができる。 $ cat output_file Linux 2.6.9-5.25AX (TAMA09) 09/07/05 Time: 12:38:51 avg-cpu: %user %nice 0.49 0.00 %sys %iowait %idle 0.08 99.29 0.14 - 3-2 - Device: avgqu-sz rrqm/s wrqm/s await sda 0.17 svctm w/s rsec/s wsec/s rkB/s 0.38 3.23 48.17 1.61 %sys %iowait %idle 0.00 0.20 99.60 w/s rsec/s wsec/s rkB/s 0.20 0.00 22.36 0.00 %sys %iowait %idle 0.00 0.20 99.80 w/s rsec/s wsec/s rkB/s 0.40 0.00 3.21 0.00 wkB/s avgrq-sz %util 0.01 5.64 6.01 0.29 350.55 r/s 0.09 24.09 107.40 Time: 12:38:56 avg-cpu: %user %nice 0.20 0.00 Device: avgqu-sz rrqm/s wrqm/s await sda 0.00 svctm wkB/s avgrq-sz %util 0.00 2.40 12.00 0.24 8.00 r/s 0.00 11.18 112.00 Time: 12:39:01 avg-cpu: %user %nice 0.00 0.00 Device: avgqu-sz rrqm/s wrqm/s await sda 0.00 5.50 svctm r/s wkB/s avgrq-sz %util 0.00 0.00 4.00 0.16 0.00 1.60 8.00 (以下略) 図 3.1-4 iostat による取得データの表示例 -t や-x 以外のオプションに関しては、iostat の man ページを参照のこと。 3.1.1.3 mpstat 一定期間毎にCPUに関する統計情報(CPU利用率、割込み発生回数など)を取得するコマ ンドである。iostatコマンドと同様、取得された結果は標準出力にテキスト形式で出力され、 データをファイルに保存するためにはファイルリダイレクトを使用する必要がある。図 3.1-5 にmpstatによるデータ取得方法を示す。 モニタリングの開始 $ mpstat 5 100 > output_file 5 秒間隔で 100 回システム統計情報を取得し & output_file にテキストデータとして保存する モニタリングの終了 $ killall mpstat 図 3.1-5 mpstat によるデータ取得手順例 - 3-3 - 図 3.1-5 で取得したデータはiostatと同じくテキスト形式で保存されているので、図 3.1-6 のようにcatなどでデータを確認できる。 $ cat output_file Linux 2.6.9-5.25AX (TAMA09) 09/07/05 12:41:13 CPU %user %nice %system %iowait %irq %soft %idle intr/s 12:41:18 all 0.00 0.00 0.00 0.00 0.00 0.00 100.00 1012.65 12:41:23 all 0.20 0.00 0.00 0.20 0.00 0.00 99.60 1009.58 12:41:28 all 0.20 0.00 0.00 0.40 0.00 0.00 99.40 1006.79 12:41:33 all 0.00 0.00 0.00 0.20 0.00 0.00 99.80 1016.06 (以下略) 図 3.1-6 mpstat による取得データの表示例 mpstat にもオプションが存在するが、それらに関しては mpstat の man ページを参照の こと。 3.1.2 評価環境 3.1.2.1 ハードウェア構成 今回の評価で使用したハードウェアの構成を以下の 表 3.1-1 に示す。 表 3.1-1 ハードウェア構成 項番 項目 評価環境 1 機種名 DELL PowerEdge 1650 2 CPU Intel PentiumIII 1.26GHz × 1 3 メモリ 1GB 4 ディスクドライブ Ultra3 SCSI 36GB × 1 5 ネットワーク Intel Corp. 82544EI Gigabit Ethernet Controller 3.1.2.2 ソフトウェア構成 今回はLinuxカーネル 2.4 ベースと 2.6 ベースのディストリビューションの環境で評価を 行った。使用したソフトウェアの構成を以下の 表 3.1-2 に示す。 表 3.1-2 ソフトウェア構成 項番 項目 カーネル 2.6 環境 1 ディストリビューション MIRACLE LINUX V4.0 beta MIRACLE LINUX V3.0 2 kernel 2.6.9-5.25AX - 3-4 - カーネル 2.4 環境 2.4.21-9.30AX 3 sysstat 5.0.5-1.1AX(RPM) 4.0.7-4.2AX(RPM) 4 stress 0.18.2-1.rf(ソース RPM からインストール) 5 IOzone 3.239(ソースからインストール) 3.1.2.3 環境準備 まず、ハードウェア環境を以下の手順で確認する。 (1) CPU の確認 以下の手順で CPU を確認する。 # cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 11 model name : Intel(R) Pentium(R) III CPU family stepping : 1 cpu MHz : 1263.699 cache size : 512 KB 1266MHz (以下略) 図 3.1-7 CPU の確認 図 3.1-7 でprocessorが”0”のものだけがあること(CPUが 1 基であること)とmodel name が”Intel(R) Pentium(R) III CPU family 1266MHz”であることを確認する。 (2) メモリの確認 以下のコマンドでメモリ量を確認する。 # cat /proc/meminfo MemTotal: 1032380 kB MemFree: 878244 kB Buffers: 9240 kB Cached: 15820 kB SwapCached: Active: Inactive: 4456 kB 21900 kB 8656 kB (以下略) 図 3.1-8 メモリの確認 図 3.1-8 でMemTotalの項目が”1032380 kB”になっていることを確認する。 - 3-5 - (3) ディスクの確認 ファイルシステムの空き容量および種類を確認するために、以下のコマンドを実行する。 # df -k Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda2 15480832 9994688 4699764 /dev/sda1 505604 14200 465300 3% /boot none 516188 1692 514496 1% /dev/shm 16943148 13131056 2951412 /dev/sda5 69% / 82% /work # mount /dev/sda2 on / type ext3 (rw) none on /proc type proc (rw) none on /sys type sysfs (rw) none on /dev/pts type devpts (rw,gid=5,mode=620) usbfs on /proc/bus/usb type usbfs (rw) /dev/sda1 on /boot type ext3 (rw) none on /dev/shm type tmpfs (rw) /dev/sda5 on /work type ext3 (rw) none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw) 図 3.1-9 ディスクの確認 df –k コマンドの実行結果から、/(ルート)パーティションと/work パーティションが存在 すること(Mounted on 列)と、mount コマンドの実行結果から tmpfs の存在(“none on /dev/shm type tmpfs (rw)”の行)を確認する。 次にソフトウェア環境を確認する。 (1) sysstat の確認 今回評価するコマンドが含まれているパッケージ sysstat がインストールされているか どうかを以下のコマンドで確認する。 $ rpm –qa | grep sysstat sysstat-5.0.5-1.1AX 図 3.1-10 sysstat のインストール確認 インストールされていない場合は、RPM パッケージをインストール CD から入手して以 下の手順でインストールする。 # rpm –ivh sysstat-5.0.5-1.1.AX.i386.rpm # rpm –ivh sysstat-4.0.7-4.2AX.i386.rpm MIRACLE LINUX V4.0 β版の場合 MIRACLE LINUX V3.0 の場合 図 3.1-11 sysstat のインストール方法 - 3-6 - (2) 負荷生成ツールの確認 擬似的に高負荷状態を発生させる負荷生成ツール(stress、 IOzone)がインストールされ ているかを以下のコマンドで確認する。 $ rpm –qa | grep stress stress-0.18.2-1.rf $ which iozone /usr/local/bin/iozone 図 3.1-12 stress と IOzone のインストール確認 stress がインストールされていない場合は、http://weather.ou.edu/~apw/projects/stress/ からソース RPM をダウンロードして、以下の手順でソース RPM からインストールする。 # rpmbuild --rebuild stress-0.18.2-1.rf.src.rpm # rpm -ivh /usr/src/asianux/RPMS/i386/stress-0.18.2-1.rf.i386.rpm 図 3.1-13 ソース RPM を用いた stress のインストール方法 IOzone がインストールされていない場合は、http://www.iozone.org/からソースコードを ダウンロードして、以下の手順でコンパイル/インストールする。 # tar xf iozone3_239.tar # cd iozone3_239 # make linux # cp –p iozone /usr/local/bin 図 3.1-14 IOzone のソースコードからのインストール方法 3.1.3 評価項目 パフォーマンス監視ツールの評価として、3 種類の代表的な負荷タイプ(ディスク I/O、 CPU、メモリ)に対して指定した時間間隔でシステムの統計情報をどの程度取得できるか を評価する。 3.1.4 評価手順 本節のパフォーマンスツール評価の手順を以下に示す。 (1) パフォーマンス監視ツールを起動 (2) (1)の 10 秒後に負荷生成を開始 (3) (2)の負荷生成終了の 10 秒後にパフォーマンス監視ツールを終了 測定では以上の手順を自動化したスクリプト load.sh を使用した。load.sh のソースコー ド、仕様、使用方法などは 2.5.1.2 節を参照のこと。 また、実際の測定においては 1 条件(同じ負荷量、モニタリングツール)に対して 3 回測定 を行っている。データ取得間隔の分布をグラフ化しているところでは、その3回の測定に おいて負荷が発生している期間におけるデータ取得間隔を集計している。 - 3-7 - 3.1.5 評価結果 まず、負荷が比較的高くない状況で sar、iostat、mpstat でモニタリングを実施し、各ツ ールが指定した時間間隔でデータが取得できるか、負荷情報を正しく取得できるかを確認 する。 stress 1 プロセスで CPU 負荷をかけた際の sar の挙動について、指定した間隔でデータ が取得できるか、負荷状況を正しく取得できるかを以下の手順で確認する。 # load.sh cpu 1 sar モニタリング開始時刻 Make Directory cpu_1_sar_050916_150411 Monitoring Start at Fri Sep 16 15:04:11 JST 2005 CPU 負荷生成開始時刻 Load Start at Fri Sep 16 15:04:21 JST 2005 stress: info: [3507] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd stress: info: [3507] successful run completed in 240s CPU 負荷生成終了時刻 Load Finish at Fri Sep 16 15:08:21 JST 2005 モニタリング終了時刻 Monitoring Finish at Fri Sep 16 15:08:31 JST 2005 /root/bin/load.sh: line 58: 3501 Terminated sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} # cd cpu_1_sar_050916_150411/ # sar -u -f sar.dat Linux 2.4.21-9.30AX (tama08) 2005年09月16日 15時04分11秒 CPU %user %nice %system %idle 15時04分16秒 all 0.00 0.00 2.01 97.99 15時04分21秒 all 0.00 0.00 2.00 98.00 15時04分26秒 all 98.00 0.00 1.60 0.40 15時04分31秒 all 98.00 0.00 2.00 0.00 15時04分36秒 all 98.00 0.00 2.00 0.00 15時04分41秒 all 98.00 0.00 2.00 0.00 15時04分46秒 all 98.00 0.00 2.00 0.00 15時04分51秒 all 98.00 0.00 2.00 0.00 15時04分56秒 all 98.20 0.00 1.80 0.00 15時05分01秒 all 98.40 0.00 1.60 0.00 15時07分56秒 all 98.00 0.00 2.00 0.00 15時08分01秒 all 98.00 0.00 2.00 0.00 15時08分06秒 all 98.00 0.00 2.00 0.00 15時08分11秒 all 98.00 0.00 2.00 0.00 15時08分16秒 all 98.00 0.00 2.00 0.00 15時08分21秒 all 98.00 0.00 2.00 0.00 負荷生成開始 (中略) - 3-8 - 負荷生成終了 15時08分26秒 all 0.20 0.00 1.61 98.19 15時08分31秒 all 0.00 0.00 2.00 98.00 Average: all 90.55 0.00 1.92 7.53 図 3.1-15 CPU 負荷時の sar の挙動 図 3.1-15 の%user(CPUがユーザ時間で使用された割合)の列を見ると負荷を掛け始めた 15:04:21 から 15:08:21 の期間で 100%に近い値になっていて、CPU負荷が発生していると いう事実が分かる。一方、それ以外の期間では%idle(CPUのアイドル率)が 100%に近い値 になっており、負荷が発生していない事実が分かる。また、一番左の列を見るとデータ取 得タイミングも指定した 5 秒通りになっていることが分かる。 次に iozone1プロセスでディスク I/O 負荷を掛けた際の iostat の挙動について、指定した 間隔でデータが取得できるか、負荷状況を正しく取得できるか確認する。 # load.sh io 1 iostat モニタリング開始時刻 Make Directory io_1_iostat_050916_151418 Monitoring Start at Fri Sep 16 15:14:18 JST 2005 Load Start at Fri Sep 16 15:14:28 JST 2005 ディスク I/O 負荷生成開始時刻 Load Finish at Fri Sep 16 15:14:49 JST 2005 ディスク I/O 負荷生成終了時刻 Monitoring Finish at Fri Sep 16 15:14:59 JST 2005 # cd io_1_iostat_050916_151418 モニタリング終了時刻 # cat iostat.dat Linux 2.4.21-9.30AX (tama08) 09/16/05 Time: 15:14:18 avg-cpu: %user %nice %sys %idle 0.70 0.00 2.47 96.83 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda 1.88 6.81 0.00 0.45 1599.78 1022.47 /dev/sda2 1.12 /dev/sda3 0.31 7.18 0.08 104.90 7.48 rsec/s wsec/s rkB/s wkB/s avgrq-sz 9.08 2678.00 4.54 1339.00 517.32 0.10 0.01 0.05 3.84 0.46 4.74 0.00 0.03 0.37 4.50 7.80 2557.56 3.90 1278.78 526.39 0.08 0.21 1.27 0.63 60.17 415.94 3.54 0.02 0.01 2.90 0.60 315.14 96.73 w/s %util 0.68 330.00 105.40 /dev/sda1 svctm r/s 3.50 14.83 0.22 Time: 15:14:23 - 3-9 - 120.34 avg-cpu: %user %nice %sys %idle 0.00 0.00 1.81 98.19 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda svctm 0.04 0.00 5.00 /dev/sda1 0.00 0.04 5.62 5.00 rkB/s 0.00 0.80 0.00 51.41 0.00 25.70 64.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.80 0.00 51.41 0.00 25.70 64.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.00 負荷生成開始 Time: 15:14:28 avg-cpu: %user %nice %sys %idle 0.00 0.00 2.00 98.00 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda svctm 0.00 0.02 3.33 /dev/sda1 0.00 3.33 0.00 0.02 0.00 0.00 0.60 0.00 8.02 0.00 4.01 13.33 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.60 0.00 8.02 0.00 4.01 13.33 0.00 0.00 0.00 0.00 0.00 0.00 0.00 rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.00 0.40 3.33 0.20 0.00 0.00 %util 0.00 0.00 /dev/sda3 w/s 0.20 0.00 3.33 r/s 0.40 0.00 /dev/sda2 wkB/s avgrq-sz 0.40 0.00 0.00 wsec/s 0.00 0.00 /dev/sda3 0.00 0.00 0.00 5.00 rsec/s 0.40 0.00 /dev/sda2 w/s %util 5.62 5.00 0.00 r/s 0.00 0.00 0.00 Time: 15:14:33 avg-cpu: %user %nice %sys %idle 3.31 0.00 95.87 0.83 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda /dev/sda1 0.00 /dev/sda2 8.66 0.00 0.00 w/s %util 0.00 21687.05 3180.99 1066.73 0.00 svctm r/s 0.00 98.62 0.00 175435.81 0.00 87717.91 1778.86 85.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 21687.05 0.00 98.62 0.00 175435.81 - 3-10 - 0.00 87717.91 1778.86 3180.99 1066.73 /dev/sda3 0.00 8.66 0.00 0.00 85.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.00 Time: 15:14:38 avg-cpu: %user %nice %sys %idle 0.00 0.00 100.00 0.00 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda svctm r/s %util 0.00 95812.00 52577.40 3836.56 /dev/sda1 0.00 /dev/sda2 0.00 0.00 0.00 0.00 95812.00 /dev/sda3 0.00 387408.00 679.66 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1140.00 0.00 774816.00 0.00 387408.00 679.66 8.77 1000.00 0.00 0.00 0.00 774816.00 0.00 52577.40 3836.56 0.00 0.00 1140.00 8.77 1000.00 0.00 0.00 w/s 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.00 3470.27 0.00 1735.14 4.12 0.00 0.00 0.00 0.00 0.00 3470.27 0.00 1735.14 4.12 0.00 0.00 Time: 15:14:43 avg-cpu: %user %nice %sys %idle 0.00 0.00 59.46 40.54 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda svctm r/s %util 0.00 227.03 13559.46 3554.87 /dev/sda1 0.00 /dev/sda2 0.00 0.00 0.00 0.00 227.03 /dev/sda3 0.00 0.00 843.24 7.44 627.03 0.00 0.00 0.00 0.00 13559.46 3554.87 0.00 0.00 843.24 7.44 627.03 0.00 0.00 w/s 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.00 負荷生成終了 Time: 15:14:48 avg-cpu: Device: avgqu-sz %user %nice %sys %idle 0.00 0.00 7.82 92.18 rrqm/s wrqm/s await svctm r/s w/s %util - 3-11 - /dev/sda 0.02 0.00 0.59 /dev/sda1 0.00 0.59 /dev/sda2 3.21 0.59 0.00 52.91 0.00 26.45 15.53 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 3.41 0.00 52.91 0.00 26.45 15.53 0.00 0.00 0.00 0.00 0.00 0.00 0.00 w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.00 2.21 0.00 44.98 0.00 22.49 20.36 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 2.21 0.00 44.98 0.00 22.49 20.36 0.00 0.00 0.00 0.00 0.00 0.00 0.00 rsec/s wsec/s rkB/s wkB/s avgrq-sz 0.20 0.00 0.00 3.41 0.00 0.00 /dev/sda3 0.00 0.00 0.00 0.59 0.00 0.20 0.00 0.00 0.02 3.21 0.00 0.00 0.00 Time: 15:14:53 avg-cpu: %user %nice %sys %idle 0.00 0.00 2.21 97.79 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda svctm 0.04 0.00 1.82 /dev/sda1 0.00 /dev/sda2 0.04 0.00 0.00 0.00 0.00 1.82 /dev/sda3 0.00 0.40 0.00 0.00 3.41 1.82 0.40 0.00 0.00 %util 3.41 1.82 r/s 0.00 0.00 0.00 Time: 15:14:58 avg-cpu: %user %nice %sys %idle 0.00 0.00 2.00 98.00 Device: rrqm/s wrqm/s avgqu-sz await /dev/sda 0.00 0.00 0.00 /dev/sda1 0.00 0.00 /dev/sda2 0.00 0.00 /dev/sda3 0.00 svctm 0.00 0.00 0.00 0.00 0.00 8.00 0.00 4.00 13.33 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.60 0.00 8.00 0.00 4.00 13.33 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.60 0.00 0.40 0.00 0.00 0.00 0.00 0.00 w/s %util 0.40 0.00 r/s 0.00 図 3.1-16 ディスク I/O 高負荷時の iostat の挙動 - 3-12 - 図 3.1-16 から負荷のかかっている期間(15:14:28 から 15:14:49)内でwrqm/s(1 秒あたりの マージされた書込みリクエスト数)やw/s(1 秒あたりの書込みリクエスト数)、wsec/s(1秒当 たりの書込みセクタ数)、wkB/s(1秒あたりの書込み量(KB))の値が高くなっており、ディ スクへの書込みが発生していることがわかる。また、Timeの項目を見ると表示されている 時刻が 5 秒間隔になっており、データ取得間隔が指定通りになっていることが分かる。 次に、stress1プロセスでメモリ負荷を掛けた際の mpstat の挙動について、指定した時 間間隔でデータを取得できるか、正しい負荷状況を取得できるか確認する。 # load.sh mem 512 mpstat Make Directory mem_512_mpstat_050916_162042 モニタリング開始時刻 Monitoring Start at Fri Sep 16 16:20:42 JST 2005 メモリ負荷生成開始時刻 Load Start at Fri Sep 16 16:20:52 JST 2005 stress: info: [699] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd stress: info: [699] successful run completed in 240s メモリ負荷生成終了時刻 Load Finish at Fri Sep 16 16:24:52 JST 2005 /root/bin/load.sh: line 57: 694 Terminated mpstat -P ALL ${INTERVAL} ${COUNT} >${SAVE_DIR}/mpstat.dat Monitoring Finish at Fri Sep 16 16:25:02 JST 2005 モニタリング終了時刻 # cd mem_512_mpstat_050916_162042/ # cat mpstat.dat Linux 2.4.21-9.30AX (tama08) 09/16/05 16:20:42 CPU %user %nice %system %idle intr/s 16:20:47 all 0.00 0.00 0.00 100.00 101.40 16:20:47 0 0.00 0.00 0.00 100.00 101.40 16:20:52 all 0.00 0.00 0.00 100.00 101.40 16:20:52 0 0.00 0.00 0.00 100.00 101.40 16:20:57 all 82.16 0.00 17.43 0.40 102.61 16:20:57 0 82.16 0.00 17.43 0.40 102.61 16:21:02 all 79.40 0.00 20.60 0.00 106.00 16:21:02 0 79.40 0.00 20.60 0.00 106.00 16:21:07 all 87.80 0.00 12.20 0.00 101.00 16:21:07 0 87.80 0.00 12.20 0.00 101.00 16:21:12 all 84.00 0.00 16.00 0.00 101.20 16:21:12 0 84.00 0.00 16.00 0.00 101.20 16:24:27 all 85.60 0.00 14.40 0.00 101.00 16:24:27 0 85.60 0.00 14.40 0.00 101.00 16:24:32 all 84.20 0.00 15.80 0.00 105.20 16:24:32 0 84.20 0.00 15.80 0.00 105.20 (中略) - 3-13 - 負荷生成開始 16:24:37 all 84.40 0.00 15.60 0.00 106.00 16:24:37 0 84.40 0.00 15.60 0.00 106.00 16:24:42 all 87.60 0.00 12.40 0.00 101.40 16:24:42 0 87.60 0.00 12.40 0.00 101.40 16:24:47 all 88.40 0.00 11.60 0.00 102.00 16:24:47 0 88.40 0.00 11.60 0.00 102.00 16:24:52 all 83.00 0.00 16.60 0.40 102.20 16:24:52 0 83.00 0.00 16.60 0.40 102.20 16:24:57 all 0.00 0.00 0.00 100.00 101.61 16:24:57 0 0.00 0.00 0.00 100.00 101.61 16:25:02 all 0.00 0.00 0.00 100.00 101.61 16:25:02 0 0.00 0.00 0.00 100.00 101.61 負荷生成終了 図 3.1-17 メモリ負荷時の mpstat の挙動 図 3.1-17 において負荷が掛かっている期間(16:20:52 から 16:24:52)の間で%sys(システム レベルでのCPU利用率)の値が約 10 から 20 程度に上昇しており、CPUがシステム時間とし て利用されていることがわかる。また、一番左の列を見ると5秒後毎の時刻が表示されて いて、データ取得タイミングが指定通りになっていることがわかる(上の例ではCPU毎のデ ータとCPU全体のデータの 2 種類が繰り返し出力されているので、同じ時刻が2回続いて いる)。 3.1.5.1 CPU 高負荷環境における障害状況 本節では、CPU 高負荷時における sar/iostat/mpstat が指定した時間間隔(5 秒)でデータ を取得できるかどうかを確認する。 以下に load.sh スクリプトを用いて stress の実行プロセス数を 100、500、1000 と変え ながら CPU 負荷を発生させた状態での、データ取得間隔の分布を示す。 (1) sar について CPUに高い負荷を掛けたときの、sarのデータ取得間隔の分布を以下の 図 3.1-18(カーネ ル 2.6 環境)および 図 3.1-19(カーネル 2.4 環境)に示す。 - 3-14 - 100 90 100 プロセスでは 80 遅延なし 70 比率(%) 60 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-18 CPU 高負荷時における sar のデータ取得間隔の分布(カーネル 2.6 環境) 100 90 80 70 比率(%) 60 50プロセス 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-19 CPU 高負荷時における sar のデータ取得間隔の分布(カーネル 2.4 環境) カーネル 2.6 環境においては CPU 負荷が 100 プロセスの場合は遅延が発生していない(= 時間間隔が 5 秒の比率が 100%になっている)。ただし 500 プロセス、1000 プロセスと負荷 を上げていくに従い遅延が発生する。一方カーネル 2.4 環境においては、50 プロセスの負 - 3-15 - 荷でもわずかながら遅延が発生し、100 プロセス、500 プロセス、1000 プロセスと負荷が 高くなるに従いより遅延が大きくなる傾向が分かる。よって、CPU 高負荷時にはカーネル 2.4 環境に比べカーネル 2.6 環境の方が sar の遅延が発生しにくいといえる。 (2) iostat について CPUに高い負荷を掛けたときの、iostatのデータ取得間隔の分布を以下の 図 3.1-20 (カ ーネル 2.6 環境)および 図 3.1-21 (カーネル 2.4 環境)に示す。 100 90 80 70 100プロセス 500プロセス 1000プロセス 50 40 負荷が高くなると 30 遅れが発生 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 0 1 比率(%) 60 時間間隔(s) 図 3.1-20 CPU 高負荷時における iostat のデータ取得間隔の分布(カーネル 2.6 環境) - 3-16 - 100 90 80 70 比率(%) 60 50プロセス 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-21 CPU 高負荷時における iostat のデータ取得間隔の分布(カーネル 2.4 環境) カーネル 2.6 環境、2.4 環境共に 100 プロセスまでは遅延が発生していないが、負荷量を 増やした場合に、カーネル 2.6 環境では遅延する回数が増えている一方で、カーネル 2.4 環 境では大きな変化は見られない。よって CPU 高負荷時の iostat はカーネル 2.4 環境の方が、 指定した通りの挙動を示す傾向がある。 (3) mpstat について CPUに高い負荷を掛けたときの、mpstatのデータ取得間隔の分布を以下の 図 3.1-22 (カ ーネル 2.6 環境)および 図 3.1-23 (カーネル 2.4 環境)に示す。 - 3-17 - 100 90 80 70 比率(%) 60 100プロセス 500プロセス 1000プロセス 50 40 負荷が高くなると 30 遅れが発生 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-22 CPU 高負荷時における mpstat のデータ取得間隔の分布(カーネル 2.6 環境) 100 90 80 70 比率(%) 60 50プロセス 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-23 CPU 高負荷時における mpstat のデータ取得間隔の分布(カーネル 2.4 環境) mpstat の場合も iostat と同じく、カーネル 2.6 環境、2.4 環境共に 100 プロセスまでは 遅延が発生していないが、負荷を増やした場合に、カーネル 2.6 環境では遅延する回数が増 えている一方、カーネル 2.4 環境では大きな変化は見られない。 以上の (1)、(2)、(3)から、CPU高負荷時にsarはカーネル 2.6/2.4 環境共に遅延が発生す - 3-18 - るが、iostat/mpstatに関してはカーネル 2.6 環境の方がカーネル 2.4 環境より遅延が発生し やすいといえる。 3.1.5.2 メモリ高負荷環境における障害状況 本節では、メモリ高負荷時における sar/iostat/mpstat が指定した時間間隔(5 秒)でデータ を取得できるかどうかを確認する。 以下に load.sh スクリプトを用いて stress 1 プロセスで 512MB、1024MB、2048MB の メモリ領域の malloc/free を繰り返すことによりメモリ負荷を発生させた状態での、データ 取得間隔の分布を示す(今回検証で用いた環境はメモリを 1GB 搭載しているため、512MB の負荷ではスワップは発生しないが、2048MB の負荷では確実にスワップが発生する)。 (1) sar について メモリに高い負荷を掛けたときの、sarのデータ取得間隔の分布を以下の 図 3.1-24 (カー ネル 2.6 環境)および 図 3.1-25 (カーネル 2.4 環境)に示す。 100 90 80 70 512MB 1024MB 2048MB 50 40 30 20 6 秒が最大 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 0 1 比率(%) 60 時間間隔(s) 図 3.1-24 メモリ高負荷時における sar のデータ取得間隔の分布(カーネル 2.6 環境) - 3-19 - 100 90 80 70 比率(%) 60 512MB 1024MB 2048MB 50 40 30 20 9 秒が最大 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-25 メモリ高負荷時における sar のデータ取得間隔の分布(カーネル 2.4 環境) sarの挙動に関して、図 3.1-24 と 図 3.1-25 を確認すると、カーネル 2.6 環境、2.4 環境 共に 512MBの負荷において遅れは発生していないが、2048MBの負荷の際に、発生頻度は 低いが遅れが発生していることがわかる。また、最大のデータ取得間隔を見ると、カーネ ル 2.6 環境では 6 秒にとどまっている一方、カーネル 2.4 環境では 9 秒まで遅れていること が分かる。よって、メモリ高負荷時のsarの遅延はカーネル 2.6 環境で改善されているとい える。 (2) iostat について メモリに高い負荷を掛けたときの、iostatのデータ取得間隔の分布を以下の 図 3.1-26 (カ ーネル 2.6 環境)および 図 3.1-27 (カーネル 2.4 環境)に示す。 - 3-20 - 100 90 80 70 比率(%) 60 512MB 1024MB 2048MB 50 40 30 20 6 秒が最大 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-26 メモリ高負荷時における iostat のデータ取得間隔の分布(カーネル 2.6 環境) 100 90 80 70 比率(%) 60 512MB 1024MB 2048MB 50 40 30 20 10 秒が最大 10 61~ 51~60 41~50 31~40 21~30 11~20 10 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-27 メモリ高負荷時における iostat のデータ取得間隔の分布(カーネル 2.4 環境) iostatの挙動に関して 図 3.1-26 と 図 3.1-27 を確認すると、sarと同じく 512MBの負荷 では遅れが発生していないが、2048MBの負荷では遅れが発生している。また、データ取得 間隔の開きもカーネル 2.4 環境の方がカーネル 2.6 環境より長い。よってsarと同じく、カ ーネル 2.6 環境においてメモリ高負荷時のiostatの遅延も改善されているといえる。 (3) mpstat について メ モ リ に 高 い 負 荷 を 掛 け た と き の 、 mpstat の デ ー タ 取 得 間 隔 の 分 布 を 以 下 の 図 - 3-21 - 3.1-28(カーネル 2.6 環境)および 図 3.1-29(カーネル 2.4 環境)に示す。 100 90 80 70 比率(%) 60 512MB 1024MB 2048MB 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-28 メモリ高負荷時における mpstat のデータ取得間隔の分布(カーネル 2.6 環境) 100 90 80 70 比率(%) 60 512MB 1024MB 2048MB 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-29 メモリ高負荷時における mpstat のデータ取得間隔の分布(カーネル 2.4 環境) mpstatの挙動に関して、図 3.1-28 と 図 3.1-29 を確認すると、sar/iostatと同じように 512MBの負荷の場合は遅れが発生していないが、負荷量を増やすと遅れが発生する。ただ し、カーネルの違いによる差は顕著には見られない。 以上から、スワップの発生しない負荷(512MB 負荷)では遅れが発生しないが、2048MB の負荷のようなスワップが発生するメモリ負荷においては sar/iostat/mpstat それぞれ遅れ - 3-22 - が発生することがわかる。また、sar と iostat についてはカーネル 2.6 環境の方がカーネル 2.4 環境に比べ遅延しない傾向にあるといえる。 3.1.5.3 ディスク I/O 高負荷環境における障害状況 本節では、ディスク I/O 高負荷時における sar/iostat/mpstat が指定した時間間隔(5 秒) でデータを取得できるかどうかを確認する。 以下では load.sh スクリプトを用いて IOzone でディクス I/O 負荷を発生させた状態での、 sar/iostat/mpstat のデータ取得間隔の分布を示す。実際には IOzone の実行プロセスを 2 プロセス、5 プロセス、10 プロセスと変化させながら測定した(1 プロセスは 500MB のフ ァイル書込みを行う)。 (1) sar について ディスクに高い負荷を掛けたときの、sarのデータ取得間隔の分布を以下の 図 3.1-30(カ ーネル 2.6 環境)および 図 3.1-31(カーネル 2.4 環境)に示す。 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-30 ディスク I/O 高負荷時における sar のデータ取得間隔の分布(カーネル 2.6 環境) - 3-23 - 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-31 ディクス高負荷時における sar のデータ取得間隔の分布(カーネル 2.4 環境) 図 3.1-30 と 図 3.1-31 の結果の結果を比較するとカーネル 2.4/2.6 環境を問わずsarは大き く遅れることがわかる。 (2) iostat について ディスクに高い負荷を掛けたときの、iostatのデータ取得間隔の分布を以下の 図 3.1-32 (カーネル 2.6 環境)および 図 3.1-33 (カーネル 2.4 環境)に示す。 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-32 ディスク I/O 高負荷時における iostat のデータ取得間隔の分布(カーネル 2.6 環境) - 3-24 - 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-33 ディスク I/O 高負荷時における iostat のデータ取得間隔の分布(カーネル 2.4 環境) 一方、iostatに関しては 図 3.1-32 と 図 3.1-33 で示すようにカーネル 2.6 環境とカーネ ル 2.4 環境で結果が異なり、カーネル 2.4 環境では iozone2 プロセスでも遅れが発生してい るが、カーネル 2.6 環境では 10 プロセスでも遅れが発生していない。よって、ディスク I/O 高負荷時の iostat の挙動がカーネル 2.6 環境では改善されているといえる。 (3) mpstat について デ ィス クに高 い負 荷を掛 けた ときの 、 iostatの デー タ取得 間隔 の分布 を以 下の 図 3.1-34(カーネル 2.6 環境)および 図 3.1-35 (カーネル 2.4 環境)に示す。 - 3-25 - 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-34 ディスク I/O 高負荷時における mpstat のデータ取得間隔の分布(カーネル 2.6 環境) 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-35 ディスク I/O 高負荷時における mpstat のデータ取得間隔の分布(カーネル 2.4 環境) カーネル 2.4 環境とカーネル 2.6 環境の差異に関して iostat と同様の傾向である。 (4) I/O スケジューラの選択による挙動の違い Linux カーネル 2.6 ではブロックデバイスへの I/O リクエストを効率よく処理するため に新たな I/O スケジューリング機構が複数導入され、用途に応じて選択することができる (なお、これまでに示したでデータは MIRACLE LINUX V4.0 beta でのデフォルトである CFQ I/O スケジューラを使用した環境で取得している)。 - 3-26 - 現在利用できる I/O スケジューラは以下の 4 種類である 1. CFQ(Completed Fair Queuing): デバイス入出力を細かい単位でおこないプロ セス間で I/O を等しく分配することにより、システムの応答時間を改善する。 2. deadline: 長時間待たされている I/O 処理を優先的に処理することにより I/O リ クエスト処理時間を一定以内に保つ。一般にデータベースシステム向けとされ ている。 3. as(anticipatory): deadline タイプの改良型。同じプロセスがファイルに対して 連続した I/O を発行する一般的な傾向を利用し、プロセスごとの統計情報に基づ いて連続した領域の I/O リクエストを発行することにより I/O 処理性能の向上を 図る。 4. noop: 単純なセクタ順での I/O リクエストの並び替えと併合処理を行うのみ。 以上のI/Oスケジューラを使用した際のディスクI/O高負荷時(iozone10 プロセスで 500MBのファイル書込み)のsarのデータ取得間隔の分布を以下の 図 3.1-36 に示す。 100 90 80 70 比率(%) 60 cfq as 50 deadline noop 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-36 I/O スケジューラによる sar のデータ取得間隔の変化 図 3.1-36 からI/Oスケジューラの変更を変更しても 10 秒以上の遅延が解消される事はなく、 根本的な解決にはならない。 以上 (1)、(2)、(3)からディスクI/O高負荷環境においてはsarはカーネル 2.6/2.4 環境を問 わず遅延が発生するが、iostat/mpstatはカーネル 2.4 環境でしか遅延が発生しない。また、 (4)ディスクI/O高負荷時のsarの遅延はI/Oスケジューラーを変更しても解消されない。 3.1.5.4 評価結果のまとめ 3.1.5.1 節、3.1.5.2 節および 3.1.5.3 節で得られた評価結果の概要を 表 3.1-3 にまとめる。 - 3-27 - 表 3.1-3 高負荷環境における障害状況 負荷タイプ カーネル sar iostat mpstat sar と同程度の遅延。 sar と同程度の遅延。 2.4 負荷 100 プロセスでは 遅延なし。500 と 1000 では遅延発生。 カーネル 2.6 より遅延大 2.6 軽度の遅延(最大 6 秒) カーネル 2.6 よりも軽度の 遅延。 sar と同程度の遅延。 カーネル 2.6 よりも軽度の 遅延。 sar と同程度の遅延。 2.4 軽度の遅延(最大 9 秒) 軽度の遅延(最大 10 秒) 軽度の遅延(最大7秒) 2.6 大きな遅延発生 遅延発生なし 遅延発生なし 2.4 カーネル 2.6 と同程度 の大きな遅延発生 大きな遅延発生 遅延発生 (iostat より軽度) 2.6 CPU 負荷 メモリ負荷 I/O 負荷 3.1.5.5 考察および回避策 本節では 2.5.1.5 節および 2.5.1.6 節で述べた障害の回避するための方法およびをその効 果について述べる。 3.1.5.1 節、3.1.5.2 節および 3.1.5.3 節で確認したsar/iostat/mpstatの遅延の原因として以 下があげられる。 z ジャーナリング処理のコミット待ちによる fdatasync の遅延 z CPU 高負荷による実行権待ち (これらの原因を特定する手順は 2.5.1 節を参照のこと) 1 番目の fdatasync の遅延を回避するためには、書込み速度の速い tmpfs の利用や、負荷 の小さいファイルシステムへの出力(ジャーナリング処理の回避)などが考えられる。 また、2 番目の CPU 高負荷による実行権待ちには、プロセス優先度を変更して実行権を 得やすくするなどの回避策が考えられる。 また、ディスクI/O高負荷時にsarは遅延するが、ファイルリダイレクトを利用している iostat/mpstatは遅延しない(図 3.1-32、図 3.1-34 参照)ことから、sarにおいてもファイル リダイレクトの利用も効果があると考えられる。 以上の各方法について、どの程度障害回避の効果があるか検証した。その結果概要を 表 (4)で述べる (以下の測定においても 3.1.5.1 3.1-4 に、詳細な手順と結果を以下の (1)、(2)、(3)、 節、3.1.5.2 節および 3.1.5.3 節で実施した手順と同じく同一条件に対して 3 回測定を行い、 その結果を集計している)。 表 3.1-4 障害回避方法とその効果 項番 方法 1 tmpfs の利用 効果が確認 された負荷 考慮点 タイプ メモリ上にデータを保存する 計測結果の出力先としてディスクより ため、監視中にマシン停止など発生すると 書込み速度の速いメモリファイルシス ディスク I/O データが消失する テムを利用する CPU 高負荷状態では効果はない 方法として挙げられた背景 - 3-28 - 2 3 4 sar が遅延する環境においてもファイ ファイルリ ル リ ダ イ レ ク ト を 利 用 す る ディスク I/O ダイレクト iostat/mpstat は遅延しないばあいが の利用 る プロセス優 プロセスの実行優先度を上昇させ、 先度 実行可能状態になった際にすぐに実 CPU (NICE 値) 行権を得られるようにする の変更 負荷の小 遅延発生に影響を与えているジャー さいファイ ナリング処理はファイルシステムごと ディスク I/O ルシステ に行われる ムへ出力 sar のみ適用可能 NICE 値を変更してプロセスの優先度を上昇 させるには root 権限が必要 ディスク I/O 高負荷状態では効果がない ディスクへの負荷が非常に高い場合、効果 は小さい (1) tmpfs の利用 tmpfs はメモリ上に構築されたファイルシステムであり、通常の(ディスク上に構築され たファイルシステムと同様な)ファイルアクセスを行うことができる。OS を停止する等によ ってマウントを解除すると内容は全て破棄されるが、高速なファイルアクセスが可能なた め、一時ファイルの格納先として適している。 以下にカーネル 2.6 環境で IOzone によるディスク I/O 高負荷状況で tmpfs をデータ出力 先として用いる手順と、sar/iostat/mpstat のデータ取得間隔の分布を表す。 [root@TAMA09 shm]# cd /dev/shm tmpfs へ移動 [root@TAMA09 shm]# load.sh io 2 sar Make Directory io_2_sar_050916_160340 Monitoring Start at Fri Sep 16 16:03:40 JST 2005 Load Start at Fri Sep 16 16:03:50 JST 2005 Load Finish at Fri Sep 16 16:04:22 JST 2005 /root/bin/load.sh: line 57: 1750 Terminated ${INTERVAL} ${COUNT} Monitoring Finish at Fri Sep 16 16:04:32 JST 2005 図 3.1-37 tmpfs の利用手順 - 3-29 - sar -A -o ${SAVE_DIR}/sar.dat 100 90 遅延なし 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-38 tmpfs 使用時のディスク I/O 高負荷時における sar のデータ取得間隔の分布 この結果から、ディスク I/O 高負荷環境における sar の遅延については tmpfs の利用で 障害が解決していることが分かる。 次に tmpfs を利用した上で、stress による CPU 負荷(1000 プロセス)環境時における iostat の挙動を確認する。 100 90 80 70 比率(%) 60 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-39 tmpfs 使用時の CPU 高負荷時における iostat のデータ取得間隔の分布 図 3.1-20(ディスク上のファイルシステムを利用)と 図 3.1-39(tmpfsを利用)を比較すると、 特に6秒、7 秒の遅延は解消されず、CPU高負荷状態でtmpfsを使用することによって障害 が解決されたとは言い難い。 - 3-30 - また、tmpfs を利用する際の注意点として、マウントを解除すると出力されたデータが消 失するため、コマンド終了後はディスク(上のファイルシステム)にコピーするといったバッ クアップが必要である。 (2) ファイルリダイレクトの利用 ディスク I/O 高負荷時にバイナリファイルにデータを直接保存する sar は遅延するが、フ ァイルリダイレクトを利用する iostat/mpstat は遅延しないことから、sar でもファイルリ ダイレクトを利用するとデータ取得の不具合は解消されるのではないかと予想される。 以下にファイルリダイレクトを利用するように load.sh を修正した load_f.sh を示す(sar の出力にファイルリダイレクトを利用する以外は load.sh と内部動作や使用方法は同じ)。 #!/bin/bash if [ $# != 3 ]; then echo "Usage: ./load_f.sh <load_type> <nr of worker> <mon_type>" >& 2 exit 1 fi load_type=$1 worker=$2 mon_type=$3 export LANG=C DATE_ID=`date +%y%m%d_%H%M%S` SAVE_DIR=${load_type}_${worker}_${mon_type}_${DATE_ID} INTERVAL=5 COUNT=600 TIMEOUT=240 LOG_FILE=load.log mkdir ${SAVE_DIR} echo "Make Directory ${SAVE_DIR}" | tee -a ${LOG_FILE} # Start Monitoring echo "Monitoring Start at `date`" | tee -a ${LOG_FILE} if [ ${mon_type} = sar ]; then ファイルリダイレクトを 使用 sar -A ${INTERVAL} ${COUNT} > ${SAVE_DIR}/sar.dat & elif [ ${mon_type} = iostat ]; then iostat –t -x ${INTERVAL} ${COUNT} > ${SAVE_DIR}/iostat.dat & - 3-31 - else mpstat -P ALL ${INTERVAL} ${COUNT} > ${SAVE_DIR}/mpstat.dat & fi sleep 10 # Start Load echo "Load Start at `date`" | tee -a ${LOG_FILE} if [ ${load_type} = cpu ]; then stress -c ${worker} -t ${TIMEOUT} elif [ ${load_type} = mem ]; then stress -m 1 --vm-bytes ${worker}M -t ${TIMEOUT} else iozone_wrap ${worker} 500 fi echo "Load Finish at `date`" | tee -a ${LOG_FILE} sleep 10 # Stop Monitoring if [ ${mon_type} = sar ]; then killall sar killall sadc elif [ ${mon_type} = iostat ]; then killall iostat else killall mpstat fi echo "Monitoring Finish at `date`" | tee -a ${LOG_FILE} 図 3.1-40 sar の出力にファイルリダイレクトを利用するスクリプト load_f..sh 以下にカーネル 2.6 環境で IOzone によるディスク I/O 高負荷状況でファイルリダイレク トを利用した場合の、sar のデータ取得間隔の分布を示す。 - 3-32 - 100 90 遅延なし 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-41 ファイルリダイレクト使用時のディスク I/O 高負荷時における sar のデータ取得間隔 の分布 上の結果から、データ取得間隔は指定どおりの 5 秒になっている。よって、sar のスロー ダウンに関してファイルリダイレクトの使用は有効であるといえる。 (3) プロセス優先度(NICE 値)の変更 負荷プロセスが多数存在すると、パフォーマンス監視ツールのプロセスが実行可能状態 になってから実際に実行権を得るまでに遅延が発生する場合がある。それを防ぐためにプ ロセスの優先度(NICE 値)を nice コマンドで上昇させ、実行可能になると直ちに実行権を取 得できるようにすることで、遅延を回避することができると考えられる。 以下に、sar/iostat/mpstat の NICE 値を”-20”に設定するように load.sh を変更した load_n.sh を示す。ちなみに、sar/iostat/mpstat の NICE 値を変更する以外は、load_n.sh の内部処理や使用方法は load.sh と同じである。 #!/bin/bash if [ $# != 3 ]; then echo "Usage: ./load.sh <load_type> <nr of worker> <mon_type>" >& 2 exit 1 fi load_type=$1 worker=$2 mon_type=$3 - 3-33 - export LANG=C DATE_ID=`date +%y%m%d_%H%M%S` SAVE_DIR=${load_type}_${worker}_${mon_type}_${DATE_ID} INTERVAL=5 COUNT=600 TIMEOUT=240 LOG_FILE=load.log mkdir ${SAVE_DIR} echo "Make Directory ${SAVE_DIR}" | tee -a ${LOG_FILE} # Start Monitoring echo "Monitoring Start at `date`" | tee -a ${LOG_FILE} if [ ${mon_type} = sar ]; then nice -n -20 sar -A -o ${SAVE_DIR}/sar.dat ${INTERVAL} ${COUNT} & elif [ ${mon_type} = iostat ]; then nice -n -20 iostat –t -x ${INTERVAL} ${COUNT} > ${SAVE_DIR}/iostat.dat & else nice -n -20 mpstat -P ALL ${INTERVAL} ${COUNT} > ${SAVE_DIR}/mpstat.dat & fi nice コマンドを用いて sleep 10 優先度を変更する # Start Load echo "Load Start at `date`" | tee -a ${LOG_FILE} if [ ${load_type} = cpu ]; then stress -c ${worker} -t ${TIMEOUT} elif [ ${load_type} = mem ]; then stress -m 1 --vm-bytes ${worker}M -t ${TIMEOUT} else iozone_wrap ${worker} 500 fi echo "Load Finish at `date`" | tee -a ${LOG_FILE} sleep 10 # Stop Monitoring if [ ${mon_type} = sar ]; then - 3-34 - killall sar killall sadc elif [ ${mon_type} = iostat ]; then killall iostat else killall mpstat fi echo "Monitoring Finish at `date`" | tee -a ${LOG_FILE} 図 3.1-42 sar/iostat/mpstat の NICE 値を変更したスクリプト load_n.sh 以下にカーネル 2.6 環境で stress による CPU 高負荷状況で NICE 値をを利用した場合の、 sar/iostat/mpstat のデータ取得間隔の分布を示す。 100 90 80 70 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 0 1 比率(%) 60 時間間隔(s) 図 3.1-43 NICE 値を変更した際の CPU 高負荷時における sar のデータ取得間隔の分布 - 3-35 - 100 90 80 70 比率(%) 60 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-44 NICE 値を変更した際の CPU 高負荷時における iostat のデータ取得タイミング 100 90 80 70 比率(%) 60 100プロセス 500プロセス 1000プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-45 NICE 値を変更した際の CPU 高負荷時における mpstat のデータ取得タイミング CPU高負荷環境においてNICE値を変更しない場合(図 3.1-18(sar)、図 3.1-20(iostat)、図 3.1-22(mpstat)) と NICE 値 を 変 更 し た 場 合 ( 図 3.1-43(sar) 、 図 3.1-44(iostat) 、 図 3.1-45(mpstat))を比較すると(共にカーネル 2.6 環境)、NICEを変更することで、すべての データ取得間隔が 5 秒になるわけではないが、遅延している比率がかなり下がり、CPU負 荷に対しては一定の効果が得られている。 次に、NICE 値を変更した場合のディスク I/O 高負荷時の sar の挙動について確認する。 - 3-36 - 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-46 NICE 値を変更した場合のディスク I/O 高負荷時の sar の挙動 図 3.1-46 から遅延が解消していないことが分かり、ディスクI/O高負荷時のsarのスローダ ウンにはNICE値の変更することによって障害は解決されないことが分かる。ディスクへの 書込み完了を待つ遅延では、プロセスのスケジューリングの順番を待っているわけではな い(2.5.1.5 節参照)ため、優先度の変更の効果が現れないと考えられる。 また、NICE 値を利用してプロセスの優先順位を高くするためには root ユーザで nice コ マンドを実行する必要があるので注意が必要である。 (4) 負荷の小さいファイルシステムへの出力 ディスク I/O 高負荷時において sar が遅延するのはジャーナリング処理によるコミット待 ちが原因である(2.5.1.5 節参照)。ただし、ジャーナリング処理はファイルシステムごとに行 われるため、ディスク I/O 負荷が高いパーティショとは別のパーティションを sar の出力結 果保存先とすればコミット待ちによる遅延は回避できるものと考えられる。 以下にカーネル 2.6 環境で IOzone によるディスク I/O 高負荷状況で sar の出力先を別パ ーティションにした場合のデータ取得間隔の分布を示す。 - 3-37 - 100 90 80 70 比率(%) 60 2プロセス 5プロセス 10プロセス 50 40 30 20 10 61~ 51~60 41~50 31~40 21~30 11~20 10 9 8 7 6 5 4 3 2 1 0 時間間隔(s) 図 3.1-47 別パーティションを使用した場合のディスク I/O 高負荷時の sar のデータ取得間隔 以上の結果から、2 プロセスのケースにおいては間隔がほぼ指定通りの 5 秒になっており 一定の効果はあるが、5 プロセス/10 プロセスの負荷においては、改善がみられるものの取 得間隔が広がる場合が数回あり、スローダウンが完全に解消されるとはいえない。 ただし、今回は負荷が高いパーティションと sar の出力先パーティションが同じデバイス 上にあるため、効果が限定的であったと考えられる。それらを別の物理デバイスにすれば より高い効果が期待される。 ■まとめ 以上の(1)から(4)の結果から、sar/iostat/mpstat について以下のような利用指針を得るこ とができる。 sar、iostat、mpstat は高負荷時にデータ取得間隔が開くが、tmpfs やファイルリダイレ クトの使用、nice コマンドによる優先度の操作、結果の出力先ファイルシステムの変更で 改善されるケースがある。ただし、負荷のタイプにより遅延を発生させる原因が異なり、 1つの回避策が常にすべての問題を解決するわけではない。よって、以下のような対策が さらに必要である。 z システム内で発生する負荷のタイプ、負荷の大きさをまず分析し、それぞれのタイ プにあった適切な回避策を選択する z 複数の回避策の組み合わせ(tmpfs の利用と NICE 値の利用の併用など)を検討する - 3-38 - 3.2 プロファイラの機能評価 3.2.1 ツール概要 OProfile は、Linux 2.2/2.4/2.6 システムに対応したプロファイリングツールであり、モ ジュールや割り込みハンドラも含んだカーネルから共有ライブラリや通常アプリケーショ ンにいたる、システムのすべてをプロファイリングする能力を持っている。 プロファイリングは、様々なイベントの発生時点における PC (Program Counter) の値 をサンプリングすることによって、その瞬間にどのバイナリ中のどの箇所が CPU によって 実行中であったかという情報を記録する。この情報の蓄積を統計的に処理することによっ て、システム全体の中で一体どこの処理に偏っているのか、どこの処理に集中しているの かを把握し、例えばパフォーマンス向上を検討する材料となりえる。 サンプリングのトリガーとして設定できるイベントは CPU の種類によって異なるが、タ イマイベントはどの CPU でも利用できる。PentiumIII 系では CPU_CLK_UNHALTED、 Pentium 4 系では GLOBAL_POWER_EVENTS と呼ばれている。 OProfileの公式ページ http://oprofile.sourceforge.net/ にはソースコードだけでなく、ド キュメントやFAQが掲載されているので参考にされたい。 3.2.2 評価環境 評価に用いた評価環境を 表 3.3-1 に示す。以降の評価は、全てこの環境で行ったもので ある。 表 3-5 項 OProfile 機能評価の評価環境 項目 評価環境 番 1 ハード CPU Intel Xeon 2GHz×4 2 ウェア メモリ 5GByte ハードディスク 34GByte(SCSI)×4 3 4 ソフト ディストリビューション MIRACLE LINUX V4.0 beta 5 ウェア カーネル 2.6.9 ファイルシステム ext3(ブロックサイズ:4KByte) 7 MIRACLE LINUX V4.0 の場合、OProfile はデフォルトでインストールされているが、 カーネルプロファイリングをする場合は kernel-debuginfo パッケージがインストールされ ている必要がある。 - 3-39 - 3.2.3 評価項目 MIRACLE LINUX V4.0 において OProfile を利用するには、oprofile-0.8.2-1AX.i386.rpm パッケージに含まれている各コマンドを実行する。今回の検証に使用した3つのコマンド を 以 下 に 紹 介 す る 。 な お 、 OProfile が サ ン プ リ ン グ し た デ ー タ は デ ィ レ ク ト リ /var/lib/oprofile/samples に格納される。 コマンド 説明 opcontrol [ options ] 各種設定をする。oprofile の起動停止。 opreport [ options ] [ profile specification ] レポートを作成する opstack [ options ] [ profile specification ] コールグラフを作成する opannotate [ options ] [ profile specification ] ソースコードとプロファイルを出力する oparchive [ options ] [ profile specification ] oprofile データをアーカイブする opgprof [ options ] [ profile specification ] gprof 形式のプロファイルデータを出力 options: session:sessionlist セッションリストを指定。セッションリストの指定がない場合は、current セッションとみ なす session-exclude:sessionlist 取り除くセッションのリスト image:imagelist プロファイルするイメージのリスト image-exclude:imagelist 取り除くイメージのリスト lib-image:imagelist イメージリストと同様 lib-image-exclude:imagelist 取り除く lib-image のリスト event:eventname イベント名 count:eventcount カウント数。イベントがこの回数発生したらデータをサンプリングする unit-mask:maskvalue ユニットマスク cpu:cpulist プロファイルする CPU リスト(0から始まる) tgid:pidlist プロファイルするタスクグループを指定する - 3-40 - tid:tidlist プロファイルするスレッドを指定する。最近のスレッドライブラリを利用すると、プロセ スのすべてのスレッドは同じタスクグループ ID を共有するが異なるスレッド ID を持つ /usr/bin/opcontrol 機能: 各種設定変更や起動・停止といった OProfile のコントロールを行う。 オプション: --vmlinux=<kernel file> デバッグ情報入りカーネルファイルを指定する --no-vmlinux カーネルファイルを持っていなく、カーネルプロ ファイリングを取りたくない時指定する --help ヘルプを表示する --version バージョンを表示する --init oprofile のモジュールをロードする --setup プロファイリングオプションの設定をし、 /root/.oprofile/daemonrc に格納する --start-daemon oprofile デーモンを起動する。プロファイリング そのものはまだ開始しない。2.2/2.4 カーネルでは 利用できない --reset サンプリングしたデータを削除する --dump プロファイリングしたデータをデーモンへフラッ シュする --start プロファイリングを開始する --stop プロファイリングを終了する。デーモンは起動し たままである。2.2/2.4 カーネルでは利用できない --shutdown プロファイリングを終了する。デーモンも kill す る --deinit デーモンをシャットダウンし、oprofile モジュー ルと oprofilefs をアンロードする --buffer-size サンプルを格納するカーネルバッファサイズ --cpu-buffer-size CPU ごとのカーネルバッファサイズ.(2.6 のみ) --event=[event|”default”] イベントないしは”default”を指定する --separate=[none,lib,kernel,t セパレータによりサンプリングを分離する hread,cpu,all] - 3-41 - --callgraph=#depth コールグラフのサンプリングを有効にする。 #depth が0の場合、コールグラフサンプリングを 行わない。x86 で 2.6 カーネル以降で利用可能で ある --image=[name,name...|"all"] --verbose デーモンのログに詳細を出力。オーバヘッドが大 きい --kernel-range=start,end 16 進でカーネルの VMA アドレスを指定する --save=<session name> サンプリングしたデータを別名で保存する 使用例: # opcontrol --vmlinux= /usr/lib/debug/lib/modules/`uname –r`/vmlinux # opcontrol --reset # opcontrol –start /usr/bin/opreport 機能: サンプリングしたデータから、実際に解析可能なデータを抽出する。 オプション: --accumulated / -c シンボルリストのサンプル数、パーセンテージを積算する --debug-info / -g 各シンボルのソースファイルと行を表示する --demangle=none|smar t|normal --details / -d 命令毎の情報を表示 --exclude-dependent / アプリケーション依存のライブラリ、モジュール、カーネ -x ル等イメージを含めない。--separate を利用したときに意 味がある --exclude-symbols / シンボルを除外する -e [symbols] --global-percent 全体に対する比率を表示する --help / -? / --usage ヘルプを表示する --image-path / [paths] --include-symbols -p バイナリの追加検索パスを指定する。2.6 カーネル以降、モ ジュールを見つけるために必要である / symbols だけを含める -i [symbols] --long-filenames / -l フルパスを出力する - 3-42 - --merge / -m [lib, --separate セッションで分離したプロファイルデータをマ cpu, tid, tgid, ージする unitmask, all] --no-header プロファイリングパラメータの詳細情報を含めない --output-file / -o stdout ではなく file へ出力する [file] --reverse-sort / -r デフォルトとは逆順にソートする --show-address / -w 各シンボルの VMA アドレスを表示する --sort / -s [vma, [vma, sample, symbol, debug, image]でソートする sample, symbol, debug, image] --symbols / -l シンボルごとにリストする --threshold / -t percentage 以上のデータのシンボルだけを出力する [percentage] --verbose / -V 詳細なデバッグ情報を与える [options] --version / -v バージョンを示す 使用例 # opreport -l -p /lib/modules/$(uname -r) > ${saveDir}/summary.out 2>&1 /usr/bin/opannotate 機能: サンプリングデータが記載されたソースファイルを出力する。 オプション: --assembly / -a アセンブリを出力する。--source と一緒の場合、ソー ス、アセンブリ混在で出力する --output-dir <directory> ソースファイルの出力ディレクトリを指定する --demangle=none|smart|nor mal --exclude-dependent / -x アプリケーション依存のライブラリ、モジュール、カ ーネル等イメージを含めない。--separate を利用した ときに意味がある --exclude-symbols / -e シンボルを除外する [symbols] --help / -? / --usage ヘルプを表示する - 3-43 - --image-path / -p [paths] バイナリの追加検索パスを指定する。2.6 カーネル以 降、モジュールを見つけるために必要である files だけを含める --include-file [files] --include-symbols / -i symbols だけを含める [symbols] --objdump-params [params] objdump を呼ぶときの追加のパラメータ --merge / -m [lib, cpu, tid, --separate セッションで分離したプロファイルデータ tgid, unitmask, all] をマージする --output-dir / -o [dir] 出力ディレクトリ。opannotate 出力を各ソースファ イルごとに行う --search-dirs / -d [paths] ソースファイルを検索するパス。イメージに対するデ バッグ情報が早退パスを含むとき、このオプションを 利用する必要がある --base-dirs / -b [paths] デバッグソースファイルから取り除くパス。 --search-dirs の base-dirs を探す前に行う annotate ソースを出力する。これにはバイナリのデ --source / -s バッグ情報が必要である --threshold / -t percentage 以上のデータのシンボルだけを出力する [percentage] --verbose / -V [options] 詳細なデバッグ情報を与える --version / -v バージョンを示す 使用例: # opannotate -s -o ${saveDir}/src 2> ${saveDir}/opannotate.log そのほか、opstack/opgprof/oparchive などのコマンドがある。 利用可能な性能イベント: x86info の出力: Family: 15 Model: 2 Stepping: 6 Type: 0 Brand: 12 CPU Model: Pentium 4 (Northwood) Original OEM Processor name string: Intel(R) Xeon(TM) MP CPU 2.20GHz Feature flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflsh dtes acpi mmx fxsr sse sse2 selfsnoop ht acc pbe Extended feature flags: cntx-id Instruction trace cache: - 3-44 - Size: 12K uOps 8-way associative. L1 Data cache: Size: 8KB Sectored, 4-way associative. line size=64 bytes. L2 unified cache: Size: 512KB Sectored, 8-way associative. line size=64 bytes. L3 unified cache: Size: 2MB 8-way associative. line size=64 bytes. Instruction TLB: 4K, 2MB or 4MB pages, fully associative, 128 entries. Data TLB: 4KB or 4MB pages, fully associative, 64 entries. The physical package supports 1 logical processors このマシンの利用可能な性能評価イベントは、opcontrol –list-events で得られる。性能 評価イベントは CPU アーキテクチャに依存するので注意が必要である。例えば Pentium III と Pentium 4/Intel Xeon 系では取得できるイベントはまったく異なる。 各イベントの詳細については、IA-32 Intel Architecture Software Developer’s Manual、 Volume 3: System Programming Guide、 Appendix A を参照のこと。 表 3-6Pentium4/Xeon の性能評価イベント oprofile: available events for CPU type "P4 / Xeon" See Intel Architecture Developer's Manual Volume 3, Appendix A and Intel Architecture Optimization Reference Manual (730795-001) イベント名およびユニットマスク GLOBAL_POWER_EVENTS: (counter: 0, 4) time during which processor is not stopped (min count: 3000) Unit masks (default 0x1) ---------0x01: mandatory BRANCH_RETIRED: (counter: 3, 7) retired branches (min count: 3000) Unit masks (default 0xc) ---------0x01: branch not-taken predicted 0x02: branch not-taken mispredicted - 3-45 - 0x04: branch taken predicted 0x08: branch taken mispredicted MISPRED_BRANCH_RETIRED: (counter: 3, 7) retired mispredicted branches (min count: 3000) Unit masks (default 0x1) ---------0x01: retired instruction is non-bogus BPU_FETCH_REQUEST: (counter: 0, 4) instruction fetch requests from the branch predict unit (min count: 3000) Unit masks (default 0x1) ---------0x01: trace cache lookup miss ITLB_REFERENCE: (counter: 0, 4) translations using the instruction translation lookaside buffer (min count: 3000) Unit masks (default 0x7) ---------0x01: ITLB hit 0x02: ITLB miss 0x04: uncacheable ITLB hit MEMORY_CANCEL: (counter: 2, 6) cancelled requesets in data cache address control unit (min count: 3000) Unit masks (default 0x8) ---------0x04: replayed because no store request buffer available 0x08: conflicts due to 64k aliasing MEMORY_COMPLETE: (counter: 2, 6) completed split (min count: 3000) Unit masks (default 0x3) ---------0x01: load split completed, excluding UC/WC loads 0x02: any split stores completed 0x04: uncacheable load split completed 0x08: uncacheable store split complete LOAD_PORT_REPLAY: (counter: 2, 6) replayed events at the load port (min count: 3000) Unit masks (default 0x2) ---------- - 3-46 - 0x02: split load STORE_PORT_REPLAY: (counter: 2, 6) replayed events at the store port (min count: 3000) Unit masks (default 0x2) ---------0x02: split store MOB_LOAD_REPLAY: (counter: 0, 4) replayed loads from the memory order buffer (min count: 3000) Unit masks (default 0x3a) ---------0x02: replay cause: unknown store address 0x08: replay cause: unknown store data 0x10: replay cause: partial overlap between load and store 0x20: replay cause: mismatched low 4 bits between load and store addr BSQ_CACHE_REFERENCE: (counter: 0, 4) cache references seen by the bus unit (min count: 3000) Unit masks (default 0x73f) ---------0x01: read 2nd level cache hit shared 0x02: read 2nd level cache hit exclusive 0x04: read 2nd level cache hit modified 0x08: read 3rd level cache hit shared 0x10: read 3rd level cache hit exclusive 0x20: read 3rd level cache hit modified 0x100: read 2nd level cache miss 0x200: read 3rd level cache miss 0x400: writeback lookup from DAC misses 2nd level cache IOQ_ALLOCATION: (counter: 0) bus transactions (min count: 3000) Unit masks (default 0xefe1) ---------0x01: bus request type bit 0 0x02: bus request type bit 1 0x04: bus request type bit 2 0x08: bus request type bit 3 0x10: bus request type bit 4 0x20: count read entries 0x40: count write entries 0x80: count UC memory access entries - 3-47 - 0x100: count WC memory access entries 0x200: count write-through memory access entries 0x400: count write-protected memory access entries 0x800: count WB memory access entries 0x2000: count own store requests 0x4000: count other / DMA store requests 0x8000: count HW/SW prefetch requests IOQ_ACTIVE_ENTRIES: (counter: 4) number of entries in the IOQ which are active (min count: 3000) Unit masks (default 0xefe1) ---------0x01: bus request type bit 0 0x02: bus request type bit 1 0x04: bus request type bit 2 0x08: bus request type bit 3 0x10: bus request type bit 4 0x20: count read entries 0x40: count write entries 0x80: count UC memory access entries 0x100: count WC memory access entries 0x200: count write-through memory access entries 0x400: count write-protected memory access entries 0x800: count WB memory access entries 0x2000: count own store requests 0x4000: count other / DMA store requests 0x8000: count HW/SW prefetch requests BSQ_ALLOCATION: (counter: 0) allocations in the bus sequence unit (min count: 3000) Unit masks (default 0x21) ---------0x01: (r)eq (t)ype (e)ncoding, bit 0: see next bit 0x02: rte bit 1: 00=read, 01=read invalidate, 10=write, 11=writeback 0x04: req len bit 0 0x08: req len bit 1 0x20: request type is input (0=output) 0x40: request type is bus lock 0x80: request type is cacheable 0x100: request type is 8-byte chunk split across 8-byte boundary 0x200: request type is demand (0=prefetch) - 3-48 - 0x400: request type is ordered 0x800: (m)emory (t)ype (e)ncoding, bit 0: see next bits 0x1000: mte bit 1: see next bits 0x2000: mte bit 2: 000=UC, 001=USWC, 100=WT, 101=WP, 110=WB X87_ASSIST: (counter: 3, 7) retired x87 instructions which required special handling (min count: 3000) Unit masks (default 0x1f) ---------0x01: handle FP stack underflow 0x02: handle FP stack overflow 0x04: handle x87 output overflow 0x08: handle x87 output underflow 0x10: handle x87 input assist MACHINE_CLEAR: (counter: 3, 7) cycles with entire machine pipeline cleared (min count: 3000) Unit masks (default 0x1) ---------0x01: count a portion of cycles the machine is cleared for any cause 0x04: count each time the machine is cleared due to memory ordering issues 0x40: count each time the machine is cleared due to self modifying code TC_MS_XFER: (counter: 1, 5) number of times uops deliver changed from TC to MS ROM (min count: 3000) Unit masks (default 0x1) ---------0x01: count TC to MS transfers UOP_QUEUE_WRITES: (counter: 1, 5) number of valid uops written to the uop queue (min count: 3000) Unit masks (default 0x7) ---------0x01: count uops written to queue from TC build mode 0x02: count uops written to queue from TC deliver mode 0x04: count uops written to queue from microcode ROM INSTR_RETIRED: (counter: 3, 7) retired instructions (min count: 3000) Unit masks (default 0x1) ---------0x01: count non-bogus instructions which are not tagged 0x02: count non-bogus instructions which are tagged 0x04: count bogus instructions which are not tagged - 3-49 - 0x08: count bogus instructions which are tagged UOPS_RETIRED: (counter: 3, 7) retired uops (min count: 3000) Unit masks (default 0x1) ---------0x01: count marked uops which are non-bogus 0x02: count marked uops which are bogus UOP_TYPE: (counter: 3, 7) type of uop tagged by front-end tagging (min count: 3000) Unit masks (default 0x2) ---------0x02: count uops which are load operations 0x04: count uops which are store operations RETIRED_MISPRED_BRANCH_TYPE: (counter: 1, 5) retired mispredicted branched, selected by type (min count: 3000) Unit masks (default 0x1f) ---------0x01: count unconditional jumps 0x02: count conditional jumps 0x04: count call branches 0x08: count return branches 0x10: count indirect jumps RETIRED_BRANCH_TYPE: (counter: 1, 5) retired branches, selected by type (min count: 3000) Unit masks (default 0x1f) ---------0x01: count unconditional jumps 0x02: count conditional jumps 0x04: count call branches 0x08: count return branches 0x10: count indirect jumps TC_DELIVER_MODE: (counter: 1, 5) duration (in clock cycles) in the trace cache and decode engine (min count: 3000) Unit masks (default 0x4) ---------0x04: processor is in deliver mode 0x20: processor is in build mode PAGE_WALK_TYPE: (counter: 0, 4) - 3-50 - page walks by the page miss handler (min count: 3000) Unit masks (default 0x1) ---------0x01: page walk for data TLB miss 0x02: page walk for instruction TLB miss FSB_DATA_ACTIVITY: (counter: 0, 4) DRDY or DBSY events on the front side bus (min count: 3000) Unit masks (default 0x3f) ---------0x01: count when this processor drives data onto bus 0x02: count when this processor reads data from bus 0x04: count when data is on bus but not sampled by this processor 0x08: count when this processor reserves bus for driving 0x10: count when other reserves bus and this processor will sample 0x20: count when other reserves bus and this processor will not sample BSQ_ACTIVE_ENTRIES: (counter: 4) number of entries in the bus sequence unit which are active (min count: 3000) Unit masks (default 0x21) ---------0x01: (r)eq (t)ype (e)ncoding, bit 0: see next bit 0x02: rte bit 1: 00=read, 01=read invalidate, 10=write, 11=writeback 0x04: req len bit 0 0x08: req len bit 1 0x20: request type is input (0=output) 0x40: request type is bus lock 0x80: request type is cacheable 0x100: request type is 8-byte chunk split across 8-byte boundary 0x200: request type is demand (0=prefetch) 0x400: request type is ordered 0x800: (m)emory (t)ype (e)ncoding, bit 0: see next bits 0x1000: mte bit 1: see next bits 0x2000: mte bit 2: 000=UC, 001=USWC, 100=WT, 101=WP, 110=WB SSE_INPUT_ASSIST: (counter: 2, 6) input assists requested for SSE or SSE2 operands (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type PACKED_SP_UOP: (counter: 2, 6) packed single precision uops (min count: 3000) - 3-51 - Unit masks (default 0x8000) ---------0x8000: count all uops of this type PACKED_DP_UOP: (counter: 2, 6) packed double precision uops (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type SCALAR_SP_UOP: (counter: 2, 6) scalar single precision uops (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type SCALAR_DP_UOP: (counter: 2, 6) scalar double presision uops (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type 64BIT_MMX_UOP: (counter: 2, 6) 64 bit integer SIMD MMX uops (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type 128BIT_MMX_UOP: (counter: 2, 6) 128 bit integer SIMD SSE2 uops (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type X87_FP_UOP: (counter: 2, 6) x87 floating point uops (min count: 3000) Unit masks (default 0x8000) ---------0x8000: count all uops of this type X87_SIMD_MOVES_UOP: (counter: 2, 6) x87 FPU, MMX, SSE, or SSE2 loads, stores and reg-to-reg moves (min count: 3000) Unit masks (default 0x18) ---------0x08: count all x87 SIMD store/move uops - 3-52 - 0x10: count all x87 SIMD load uops 3.2.4 評価手順 OProfile を利用して cache pollution が発生している場所を特定する。 準備: # opcontrol --vmlinux= /usr/lib/debug/lib/modules/`uname –r`/vmlinux ${OPevent} ここで${OPevent}に測定したいイベント名、サンプリング間隔、イベントマスク、カー ネル、ユーザーでのプロファイリングをするかいなかを指定する。 イベント設定例: -e=BSQ_CACHE_REFERENCE:3000:0x200:1:1 イベント名は先に示した 表 3-6Pentium4/Xeonの性能評価イベントを参照し、キャッシ ュ関連のもの(BSQ_CACHE_REFERENCE)を選び、イベントマスクは 0x200(3rd level cache miss)を設定している。 サンプリングデータのリセット: # opcontrol –reset 開始(サンプリングの開始): # opcontrol –start サンプリングの開始から終了の間に、測定したい、ベンチマークなどを流す。 終了(サンプリングの終了): # opcontrol –shutdown データ処理(各種統計データの抽出と、元データの保存) : # opreport –l –p /lib/modules/$(uname -r) > ${saveDir}/summary.out 2>&1 # opreport –l –p /lib/modules/$(uname -r) > ${saveDir}/detail.out 2>&1 # opannotate -s -d /usr/src/linux-$(uname -r) ¥ -o ${saveDir}/src > ${saveDir}/opannotate.log 2>&1 # opcontrol -save=${session} 以上の手順によって、計測パターンごとに以下の 4 種類のデータが得られる。 表 3-3-7 OProfile のデータ ファイル summary.out カーネルの各シンボルごとのプロファイリン グデータ - 3-53 - ファイル detail.out シンボルを細分化した、命令単位のデータ ディレクトリ ./src/ 下のファイル プロファイリングデータを併記したソースコ ード ディレクトリ OProfile サンプリング生データ保存先。これ /var/lib/oprofile/samples/session/ をもとに別形式のデータを抽出可能。 summary.out のフォーマットは次の通り。占有率の高い順にシンボルがリストされ る。 CPU: P4 / Xeon with 2 hyper-threads, speed 2993.03 MHz (estimated) CPU の種類とクロック Counted GLOBAL_POWER_EVENTS events (time during which processor is not stopped) with a unit mask of 0x01 (mandatory) count 100000 samples % サンプル数 測定したイベントとサンプリング頻度 image name 占有率 イメージ名 app name アプリケーション名 symbol name シンボル名 215795 5.6329 vmlinux vmlinux __copy_user_zeroing_intel_nocache 104172 2.7192 jbd.ko jbd journal_stop 102359 2.6719 jbd.ko jbd journal_add_journal_head 93709 2.4461 jbd.ko jbd do_get_write_access 89073 2.3251 vmlinux vmlinux __might_sleep 74740 1.9509 jbd.ko jbd journal_put_journal_head 73707 1.9240 jbd.ko jbd journal_dirty_metadata 68674 1.7926 vmlinux vmlinux __find_get_block 63702 1.6628 jbd.ko jbd journal_cancel_revoke 63660 1.6617 vmlinux vmlinux __brelse 62624 1.6347 jbd.ko jbd journal_dirty_data 57284 1.4953 vmlinux vmlinux mark_offset_tsc 55985 1.4614 jbd.ko jbd start_this_handle 54099 1.4121 vmlinux vmlinux __cond_resched 47993 1.2528 vmlinux vmlinux __mark_inode_dirty 47878 1.2498 vmlinux vmlinux unlock_buffer 42326 1.1048 ext3.ko ext3 ext3_new_block 39625 1.0343 vmlinux vmlinux __block_write_full_page 図 3.2-1 pattern9-0-cpu2-0-09081635/summary.out detail.out のフォーマットは次の通り。シンボルごとに、その内訳がサンプル数や占 有率と共にリストされる。 - 3-54 - CPU: P4 / Xeon with 2 hyper-threads, speed 2993.03 MHz (estimated) CPU の種類とクロック Counted GLOBAL_POWER_EVENTS events (time during which processor is not stopped) with a unit mask of 0x01 (mandatory) count 100000 vma samples % c01c3be1 215795 5.6329 image name app name vmlinux vmlinux symbol name __copy_user_zeroing_intel_nocache 仮想アドレス 全体に対する占有率 サンプル数 アプリケーション名 シンボル名 当該関数内での占有率 c01c3be1 86 0.0399 c01c3be2 74 0.0343 c01c3be4 35 0.0162 c01c3be5 40 0.0185 c01c3be7 10 0.0046 c01c3be8 30 0.0139 c01c3bea 117 0.0542 c01c3bed 3404 1.5774 c01c3bf0 157 0.0728 c01c3bf2 2231 1.0339 c01c3bf5 9581 4.4399 c01c3bf6 4308 1.9963 c01c3bf9 2554 1.1835 c01c3bfc 295 0.1367 c01c3c00 5485 2.5418 c01c3c04 4328 2.0056 c01c3c07 2171 1.0060 c01c3c0a 325 0.1506 c01c3c0e 4915 2.2776 図 3.2-2detail.out 3.2.5 評価結果 まず、クロック数を測定するために、GLOBAL_POWER_EVENTS を設定し、OProfile で計測してみた。 下記は CPU ビジー型のベンチマークで CPU 数 16 個のマシンで計測したものである。 __copy_from_user_ll()という関数が実行時間の約 28%強を占めている。トップ 5 の関数 の実行時間が 65%を超えているのが分かる。ここで__copy_from_user_ll()という関数は、 ユーザー空間からカーネル空間へデータをコピーする関数である。write(2)では必ず実行さ れる関数である。実装は非常に単純なデータの転送で、アルゴリズム的に工夫の余地はほ とんどないと思われた。 - 3-55 - 表 3-8 プロファイリング全体結果/ pattern9-0-cpu16-08031605 順位 シンボル サンプル数 占有率(%) 累積占有率(%) 1 __copy_from_user_ll 3201368 28.54 28.54 2 _spin_lock_irq 1870823 16.68 45.22 3 no symbols/jbd 1071441 9.55 54.77 4 _spin_lock 769409 6.86 61.63 5 no symbols/ext3 484137 4.32 65.95 __copy_from_user_ll() の 詳 細 は 表 3-9 プ ロ フ ァ イ リ ン グ __copy_from_user_ll 詳 細 /2.6.9-11.5AXのとおりである。c01c03d4 のアドレスのmovsl命令で当該関数中の約 92%を 占有している。 表 3-9 プロファイリング__copy_from_user_ll 詳細/2.6.9-11.5AX アドレス サンプル __copy_from_us 数 er_ll に対する占 命令 有率(%) c01c03d4 c01c03d6 repz 3036318 92.71 movsl %ds:(%esi),%es:(%edi) 96922 2.96 mov c01c03d8 %eax,%ecx repz movsb %ds:(%esi),%es:(%edi 6999 0.21 ) c01c03da 110331 3.37 jmp c01c03e5 c01c03e6 23495 0.71 mov %ecx,%eax repz movsl %ds:(%esi),%es:(%edi) は%ds:(%esi)から%es:(%edi)へ%ecx *4 バイト転送 する命令である。 mov 命令のコストが高いときはキャッシュミスを疑ってみる。 そこで、L3 キャッシュミスを測定してみる。 # opcontrol –e=BSQ_CACHE_REFERENCE:3000:0x200:1:1 下記のとおり、__copy_from_user_ll()でキャッシュミスが多発しているのが分かる。約 63%のキャッシュミスが、当該ルーチンで発生していて、2 位以下の寄与率は 2%以下であ る。この関数は非常にたちの悪い L3 キャッシュミスを起こしているというのがよくわかる。 CPU: P4 / Xeon, speed 2201.02 MHz (estimated) Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000 samples % app name symbol name - 3-56 - 37260 63.1772 vmlinux __copy_from_user_ll 1039 1.7617 vmlinux _spin_lock_irqsave 935 1.5854 vmlinux _spin_lock 925 1.5684 vmlinux blk_rq_map_sg 910 1.5430 vmlinux journal_add_journal_head 図 3.2-3pattern9-0-cpu4-0-08141508/summary.out L2/L3 キ ャ ッ シ ュ ヒ ッ ト は 以 下 の と お り で あ る 。 メ モ リ ア ク セ ス に 比 べ て __copy_from_user_ll()のキャッシュミスの多さが際立っている。 CPU: P4 / Xeon, speed 2201.02 MHz (estimated) Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus unit) with a unit mask of 0x3f (multiple flags) count 3000 samples % app name symbol name 118812 7.3122 vmlinux __copy_from_user_ll 82947 5.1049 vmlinux _spin_lock 65983 4.0609 vmlinux journal_add_journal_head 61903 3.8098 vmlinux __find_get_block 59457 3.6593 vmlinux journal_dirty_metadata 図 3.2-4pattern9-0-cpu4-0-08141510/summary.out CPU レジスタ L1 キャッシュ SB メインメモリ L2キャッシュ 図 3.2-5CPU、キャッシュ、メモリ構成 - 3-57 - メインメモリに CPU からアクセスするとき L1(一次)/L2(二次)キャッシュにデータがな い場合、メインメモリにメモリバス経由でアクセスしにいく。そのコストは L1 キャッシュ アクセスに比べ 100 倍以上コスト(時間)がかかる。CPU に他にするべき仕事がないと 200 ~300 クロック遊んでしまうことになる。そのため、キャッシュミスを減らすことが性能向 上のために非常に重要になってくる。 表 3-10 キャッシュのアクセスコスト デバイス アクセスコスト L1(一次)キャッシュ 2 クロック L2(二次)キャッシュ 10 クロック L3(三次)キャッシュ 50 クロック程度 メインメモリ 200~300 クロック前後 CPU がメインメモリからデータを読むとき、適当なキャッシュにデータを置く。これを cache line fill とよぶ。次回データを読むとき、同じデータがキャッシュにあれば、CPU は メインメモリからではなくキャッシュからデータを読むことができる。これをキャッシュ ヒットと呼ぶ。 CPUがキャッシュ可能なメモリへ書き込む場合、最初キャッシュにそのメモリのキャッ シュラインが存在するかチェックする。有効なキャッシュラインが存在した場合、CPUは (書き込みポリシーに依存するのだが)、メインメモリではなくキャッシュに書き込む。こ れをライトヒット(write hit)と呼ぶ。もしキャッシュをライトミスしたら(有効なキャッシ ュライン存在しない)、CPUはcache line fill, write allocationを行う。データをキャッシュ ラインに書き、そしてメインメモリへ書く。もしデータがメモリへ書かれるなら、それは 最初にストアバッファ(Store Buffer)へ書き込まれ、システムバスが利用できるようになっ たら、ストアバッファ 1からメモリへ書き込まれる。 キャッシュラインフィルするとき CPU はそのラインを新しいデータに置き換えるが、置 き換えられたデータがすぐに必要になる場合もある。必要なデータを追い出して置き換え てしまったとき cache conflict あるいは cache pollution が発生したという。 例えば書き出したデータをすぐにアクセスしないとしたら、そのデータをキャッシュに のせる必要はない。データをキャッシュにのせなければ必要なデータを追い出すこともな いので cache pollution が発生しない。 IA-32 には Non-temporal move 命令というのがある。これは、CPU レジスタからキャッ シュ(L1/L2/L3)を経由せず直接メインメモリにデータを移動する。これらの命令はレジ スタからメモリへ書き込むときキャッシュを経由しないので cache pollution を防止するの に利用することができる。 一方で、どっちもすぐにアクセスするデータなのではあるがたまたま同じキャッシュラ インに載るために cache conflict が発生している場合もある。 これを特に thrashing とよぶ。 キャッシュミスが多発しているとき、その原因がキャッシュコンフリクト(スラッシン 1 Pentium 4 および Intel Xeon プロセッサは 24 エントリのストアバッファを持つ。 - 3-58 - グ)によるものか、cache pollution によるものか見極めるのは OProfile のデータだけでは 不十分で、ソースコードを確認し分析する必要がある。 キャッシュミスが発生した時点の各種レジスタの値がわかれば、どのメモリへアクセス しているのがわかるので、そのめもりがどのキャッシュラインのセットへ割り当てられる かは分かる。しかし現状の OProfile ではそのような情報を提供していない。 例えば Pentium 4 ないし Intel Xeon プロセッサの L2 キャッシュは 512KB、キャッシュ ラインサイズは 64 バイト、8 way set associative なので 512KB/64=8192 個キャッシュラ インがある。そのキャッシュラインを 8 個で共有するので、8129/8=1024 なので、アドレ スを 1024 で割ったあまりのうち下の 64 バイト分を無視した部分が等しければ同じキャッ シュラインのセットに割り当てられる。 例えば要素が 1024 バイトの配列があったとする。この配列をアクセスすると先頭アドレ スが 1024 バイトで飛び飛びになっているので、常に同じキャッシュラインにのるので要素 を 8 個以上アクセスすると確実に cache conflict をすることになる。 同じキャッシュラインのセットということがわかれば cache conflict の可能性が高いとい うことが推定できる。 今回はソースコードを分析して cache pollution の可能性を疑い、それを解決するパッチ を作成し、評価してみた。 diff -ur linux-2.6.13/Makefile linux-2.6.13.nt/Makefile --- linux-2.6.13/Makefile 2005-08-29 08:41:01.000000000 +0900 +++ linux-2.6.13.nt/Makefile 2005-09-03 14:11:27.000000000 +0900 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 13 -EXTRAVERSION = +EXTRAVERSION = .nt NAME=Woozy Numbat # *DOCUMENTATION* diff -ur linux-2.6.13/arch/i386/lib/usercopy.c linux-2.6.13.nt/arch/i386/lib/usercopy.c --- linux-2.6.13/arch/i386/lib/usercopy.c 2005-08-29 08:41:01.000000000 2005-09-03 14:09:18.000000000 +0900 +++ linux-2.6.13.nt/arch/i386/lib/usercopy.c +0900 @@ -425,6 +425,107 @@ : "eax", "edx", "memory"); - 3-59 - return size; } + +/* Non Temporal Hint version of __copy_user_zeroing_intel */ +/* It is cache aware. */ +/* [email protected] */ +static unsigned long +__copy_user_zeroing_intel_nocache(void *to, const void __user *from, unsigned long size) +{ + int d0, d1; + + __asm__ __volatile__( + " .align 2,0x90\n" + "0: movl 32(%4), %%eax\n" + " cmpl $67, %0\n" + " jbe 2f\n" + "1: movl 64(%4), %%eax\n" + " .align 2,0x90\n" + "2: movl 0(%4), %%eax\n" + "21: movl 4(%4), %%edx\n" + " movnti %%eax, 0(%3)\n" + " movnti %%edx, 4(%3)\n" + "3: movl 8(%4), %%eax\n" + "31: movl 12(%4),%%edx\n" + " movnti %%eax, 8(%3)\n" + " movnti %%edx, 12(%3)\n" + "4: movl 16(%4), %%eax\n" + "41: movl 20(%4), %%edx\n" + " movnti %%eax, 16(%3)\n" + " movnti %%edx, 20(%3)\n" + "10: movl 24(%4), %%eax\n" + "51: movl 28(%4), %%edx\n" + " movnti %%eax, 24(%3)\n" + " movnti %%edx, 28(%3)\n" + "11: movl 32(%4), %%eax\n" + "61: movl 36(%4), %%edx\n" + " movnti %%eax, 32(%3)\n" + " movnti %%edx, 36(%3)\n" + "12: movl 40(%4), %%eax\n" - 3-60 - + "71: movl 44(%4), %%edx\n" + " movnti %%eax, 40(%3)\n" + " movnti %%edx, 44(%3)\n" + "13: movl 48(%4), %%eax\n" + "81: movl 52(%4), %%edx\n" + " movnti %%eax, 48(%3)\n" + " movnti %%edx, 52(%3)\n" + "14: movl 56(%4), %%eax\n" + "91: movl 60(%4), %%edx\n" + " movnti %%eax, 56(%3)\n" + " movnti %%edx, 60(%3)\n" + " addl $-64, %0\n" + " addl $64, %4\n" + " addl $64, %3\n" + " cmpl $63, %0\n" + " ja + " sfence \n" + "5: movl %0, %%eax\n" + " shrl $2, %0\n" + " andl $3, %%eax\n" + " cld\n" + "6: rep; movsl\n" + " movl %%eax,%0\n" + "7: rep; movsb\n" + "8:\n" + ".section .fixup,\"ax\"\n" + "9: lea 0(%%eax,%0,4),%0\n" + "16: pushl %0\n" + " pushl %%eax\n" + " xorl %%eax,%%eax\n" + " rep; stosb\n" + " popl %%eax\n" + " popl %0\n" + " jmp 8b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,16b\n" + " .long 1b,16b\n" + " .long 2b,16b\n" 0b\n" - 3-61 - + " .long 21b,16b\n" + " .long 3b,16b\n" + " .long 31b,16b\n" + " .long 4b,16b\n" + " .long 41b,16b\n" + " .long 10b,16b\n" + " .long 51b,16b\n" + " .long 11b,16b\n" + " .long 61b,16b\n" + " .long 12b,16b\n" + " .long 71b,16b\n" + " .long 13b,16b\n" + " .long 81b,16b\n" + " .long 14b,16b\n" + " .long 91b,16b\n" + " .long 6b,9b\n" + " .long 7b,16b\n" + ".previous" + : "=&c"(size), "=&D" (d0), "=&S" (d1) + : "1"(to), "2"(from), "0"(size) + : "eax", "edx", "memory"); + return size; +} + #else /* * Leave these declared but undefined. They should not be any references to @@ -434,6 +535,8 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size); unsigned long __copy_user_intel(void __user *to, const void *from, unsigned long size); +unsigned long +__copy_user_zeroing_intel_nocache(void *to, const void __user *from, unsigned long size); #endif /* CONFIG_X86_INTEL_USERCOPY */ /* Generic arbitrary sized copy. */ @@ -515,7 +618,6 @@ : "memory"); \ } while (0) - 3-62 - unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) { BUG_ON((long) n < 0); @@ -588,6 +690,21 @@ } EXPORT_SYMBOL(__copy_from_user_ll); +unsigned long +__copy_from_user_ll_nocache(void *to, const void __user *from, unsigned long n) +{ + BUG_ON((long)n < 0); +#ifdef CONFIG_X86_INTEL_USERCOPY + if ( n > 64 && cpu_has_xmm2) + n = __copy_user_zeroing_intel_nocache(to, from, n); + else + __copy_user_zeroing(to, from, n); +#else + __copy_user_zeroing(to, from, n); +#endif + return n; +} + /** * copy_to_user: - Copy a block of data into user space. * @to: Destination address, in user space. diff -ur linux-2.6.13/include/asm-i386/uaccess.h linux-2.6.13.nt/include/asm-i386/uaccess.h --- linux-2.6.13/include/asm-i386/uaccess.h 2005-08-29 08:41:01.000000000 2005-09-03 14:09:18.000000000 +0900 +++ linux-2.6.13.nt/include/asm-i386/uaccess.h +0900 @@ -413,6 +413,8 @@ const void *from, unsigned long n); unsigned long __must_check __copy_from_user_ll(void *to, const void __user *from, unsigned long n); +unsigned long __must_check __copy_from_user_ll_nocache(void *to, - 3-63 - + const void __user *from, unsigned long n); /* * Here we special-case 1, 2 and 4-byte copy_*_user invocations. On a fault @@ -502,11 +504,40 @@ } static inline unsigned long +__copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n) +{ + if (__builtin_constant_p(n)) { + unsigned long ret; + + switch (n) { + case 1: + __get_user_size(*(u8 *)to, from, 1, ret, 1); + return ret; + case 2: + __get_user_size(*(u16 *)to, from, 2, ret, 2); + return ret; + case 4: + __get_user_size(*(u32 *)to, from, 4, ret, 4); + return ret; + } + } + return __copy_from_user_ll_nocache(to, from, n); +} + +static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_sleep(); return __copy_from_user_inatomic(to, from, n); } + +static inline unsigned long +__copy_from_user_nocache(void *to, const void __user *from, unsigned long n) +{ + might_sleep(); - 3-64 - + return __copy_from_user_inatomic_nocache(to, from, n); +} + unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n); unsigned long __must_check copy_from_user(void *to, diff -ur linux-2.6.13/mm/filemap.c linux-2.6.13.nt/mm/filemap.c --- linux-2.6.13/mm/filemap.c 2005-08-29 08:41:01.000000000 +0900 +++ linux-2.6.13.nt/mm/filemap.c 2005-09-03 14:09:18.000000000 +0900 @@ -1726,7 +1726,7 @@ int copy = min(bytes, iov->iov_len - base); base = 0; - left = __copy_from_user_inatomic(vaddr, buf, copy); + left = __copy_from_user_inatomic_nocache(vaddr, buf, copy); copied += copy; bytes -= copy; vaddr += copy; diff -ur linux-2.6.13/mm/filemap.h linux-2.6.13.nt/mm/filemap.h --- linux-2.6.13/mm/filemap.h 2005-08-29 08:41:01.000000000 +0900 +++ linux-2.6.13.nt/mm/filemap.h 2005-09-03 16:47:39.000000000 +0900 @@ -34,13 +34,13 @@ int left; kaddr = kmap_atomic(page, KM_USER0); - left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); + left = __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes); kunmap_atomic(kaddr, KM_USER0); if (left != 0) { /* Do it the slow way */ kaddr = kmap(page); - left = __copy_from_user(kaddr + offset, buf, bytes); + left = __copy_from_user_nocache(kaddr + offset, buf, bytes); kunmap(page); } return bytes - left; - 3-65 - 3.2.6 readprofile readprofile [ options ] readprofile コマンドは、/proc/profile の情報を標準出力に出力する。出力される情報は、 3 種類の情報から構成されている。最初の項目は、クロックチック(clock tick)である。 2 番 目は、たくさんの時間を消費しているカーネル内部の C の関数名である。 3 番目の項目 は、手続きの「負荷」を正規化したもので、関数の長さとクロック数の比率として計算さ れる。これらの項は、読み取りやすいように空白を入れ、桁を揃えて出力される。 表 3-11readprofile のオプション オプション 説明 -m mapfile マ ッ プ フ ァ イ ル を 指 定 す る 。 デ フ ォ ル ト で は 、 /usr/src/linux/System.map が使用される。現在のカーネルが最後にコ ンパイルしたものでない場合、または System.map を他の場所に保存し ている場合は 、コ マンドライン上でマップファイルを指定する必要が ある。マップファイル名の最後が ‘.gz’ となっている場合は、実行時 に自動的に伸長される -p profile 別 の プ ロ フ ァ イ リングバッファを指定する。デフォルトでは、 /proc/profile が使用される。別のプロファイリングバッファを使 用す ると、カーネルプロファイリングを「凍結」した後でプロファイリング 情報を読む場合などに有用である。 /proc/profile は、‘cat’ や、‘cp’ コマンドを使ってコピーすることができる。プログラムがプロファイリ ングバッファのサイズを前もって取得する必要があるため 、 readprofile-1.1 で行なわれていた、圧縮されたプロファイリングバッ ファはサポートされなくなった -i カーネルプロファイリング情報の表示。このオプションを指定すると、 readprofile は、カーネルによって使用されているプロファイリングステ ップのみを表示する。プロファイリングステップはプロファイリングバ ッファの精度であり、(make config を使った)カーネルの設定、またはカ ーネルのコマンドラインで指定される。-t(terse:簡 潔モード)スイッチが -i と一緒に指定されると、単に 10 進数の数字のみが表示される -a マップファイル中のすべてのシンボルを表示する。デフォルトでは、使 用クロック数が 0 の手続きは出力されない -b 各メモリ領域に対する出現数のカウントを表示する -r プロファイリングバッファの内容を初期化する。 /proc/profile は、スー - 3-66 - パーユーザーだけが書き込み可能で、一般ユーザーは読み込みしかでき ないため、このオプションを使用するには、スーパーユーザーの権限が 必要となる。しかし、 readprofile を setuid 0 とすることで 、特権を 持たないユーザーでもプロファイリングバッファの内容を初期化するこ とができる -M multiplier カーネルがプロファイリング割り込みを各 CPU に送る周期を変更でき るアーキテクチャもある。このオプションにより、周期をシステムクロ ック周波数 HZ の倍数で設定できる。 i386-SMP (2.2 と 2.4 カーネル) と sparc64-SMP (2.4 カーネル) でサポートされている。このオプショ ンはプロファイリングバッファの初期化も行うので、スー パーユーザー 特権が必要である 詳細モード。出力は 4 つの項目から構成され、それぞれ空白により桁が -v 揃えられる。最初の項目はカーネルの関数の RAM アドレス、2 番目の 項目は関数の名前、 3 番目の項目は使用したクロック数、最後の項目に は正規化された負荷が表示される バージョン情報の表示。 readprofile は、現在のバージョン番号を表示 -V した後、終了する 例: # readprofile |sort -nr +2 |head -10 7479250 default_idle 159132.9787 548 kunmap_atomic 49.8182 567 this_rq_lock 14.5385 7487519 total 3.9394 500 probe_irq_mask 3.8760 156 cpu_idle 2.6441 111 kpmd_ctor 1.9821 5 zlib_inflate_codes_free 1.2500 225 __add_to_swap_cache 1.2295 831 do_page_fault 1.0519 図 3.2-6 最もクロックを消費した関数上位 10 個の表示 readprofile を実行するためには、カーネル起動時にカーネルパラメタ profile=1 など与え ておかなければならない。 title Asianux (2.6.9-11.11AXsmp) root (hd0,0) kernel /vmlinuz-2.6.9-11.11AXsmp ro root=LABEL=/ profile=1 initrd /initrd-2.6.9-11.11AXsmp.img - 3-67 - 図 3.2-7grub.conf の設定 3.2.7 考察 カーネルプロファイラとして、OProfile と readprofile を比較検討する。 OProfile は CPU が提供する各種ハードウェアイベントをプロファイリングするが、 readprofile はタイマによるサンプリング機能だけである。 また取得可能なイメージも OProfile はカーネル、ユーザプログラムどちらもプロファイ リングできるが、readprofile はカーネルプロファイリングだけである。 レポート機能も、OProfile はソースコードとの対比をとったり、様々な形式に対応して いるが、readprofile はアドレスとシンボル名を対比させるだけである。 OProfile はそれ以外にもコールグラフの測定、 プロファイリングデータのアーカイブ化、 gprof 形式でのデータ出力など豊富な機能を持つ。 OProfile の起動、停止は opcontrol で行う。readprofile を利用するときは起動時にカー ネルパラメータで設定しないとならない。一度起動した readprofile を停止する方法は再起 動以外ない。 OProfile はユーザランドのツールをインストールする必要がある。2.6 カーネルへは組み 込まれているので特に新たなカーネルを作成する必要はない。readprofile は既に組み込ま れているのでインストールの作業等は必要ない。 かつては、カーネルのプロファイリングは readporfile がカーネルに標準に装備されてい たのでよく利用されていたが、機能の充実度、使いやすさ、カーネルに既に組み込まれた 点などを考えると OProfile を利用を推奨する。 - 3-68 - 3.3 システムコールトレーサの評価 3.3.1 システムコールトレーサの概要 システムコールトレーサは、カーネル空間とユーザ空間のインタフェースである、シス テムコールをトレースするツールである。システムコールを追跡することで、想定通りの 正しい順序でシステムコールが発行されているか、期待していない結果やエラーを返して いるシステムコールがないか、などを確認することができる。 Linux で利用できるシステムコールトレーサとしては主に strace と ltrace が使われてい る。strace はシステムコールを追跡するツールであり、追跡するプロセスの子プロセスが 発行するシステムコールも追跡可能である。ltrace は strace とほぼ同様の機能に加え、ダ イナミックライブラリ内のライブラリ関数コールも追述できるようにしたツールである。 以下では両ツールを代表し、strace に関して、その機能および信頼性の評価を行った。 3.3.2 strace 評価環境 strace評価に用いた評価環境を 表 3.3-1 に示す。以降の評価は、全てこの環境で行った ものである。 表 3.3-1 項 strace 機能評価の評価環境 項目 評価環境 番 1 ハード CPU Pentium III 800MHz×1 2 ウェア メモリ 512MByte ハードディスク 18GByte(SCSI) 3 4 ソフト ディストリビューション Fedora Core 3 5 ウェア カーネル 2.6.9 6 ファイルシステム ext3(ブロックサイズ:4KByte) 7 strace 4.5.8 3.3.3 strace 機能評価 ここでは、strace の全オプションについて、man ページ通り動くかどうかを評価した。 また、man ページ化されていないオプションが存在するかどうかも、合わせて評価した。 3.3.3.1 評価手順 strace 機能評価の際の評価手順を、以下に示す。 - 3-69 - (1) ls コマンド等を strace 経由で実行。その際に、strace のオプションを変化させて確認す る。 (2) オプション分(1)の手順を繰り返す。 (3) strace のソースを参照し、man ページ化されていないオプションの有無を確認する。 3.3.3.2 結果 strace機能評価の結果を 表 3.3-2 に示す。 表 3.3-2 # 1 2 3 オプション -c -d -f 4 strace 機能評価結果 man ページ概要 評価結果 各システムコールの所要時間、呼出し回数、エ man ページ通り ラー発生回数を統計表示する strace 自身のデバッグ情報を標準エラー出力 man ページ通り に表示する トレース対象プログラムから(v)fork で生成さ man ページ通り れたプロセスも strace のトレース対象とする -o filename オプションが指定され、かつトレ man ページ通り ース対象プログラムから子プロセスを生成す る場合、以下のようにトレース結果を別ファイ -ff ルに保存する。 トレース対象プログラムのトレース出力先: filename 生成された子プロセスのトレース出力先: filename.pid 5 -F トレース対象プログラムから vfork で生成され -f オ プ シ ョ ン の み で たプロセスも strace のトレース対象とする vfork トレースが可能 6 -h strace のコマンドヘルプを表示する man ページ通り 7 -i システムコール時の命令ポインタを表示する man ページ通り アタッチやデタッチに関するメッセージを抑 man ページ通り 8 9 10 11 -q -r -t -tt 12 止する 各システムコール間の相対時間を表示する man ページ通り 各システムコールのトレース開始時刻 man ページ通り hh:mm:ss をトレース結果の前に表示する -t オプションで記録する時刻のフォーマット にμ秒の単位を追加する(hh:mm:ss.μ) -tt オプションのようにμ秒の単位まで表示す -ttt man ページ通り るが、時分秒の部分は 1970 年 1 月 1 日 00:00:00 UTC からの秒数として表示する(秒数.μ) - 3-70 - man ページ通り # 13 14 15 16 17 オプション -T -v -V -x -xx 18 man ページ概要 評価結果 各システムコールの開始から終了までの時間 man ページ通り を記録する 構造体の情報を表示する際に、省略しないよう にする strace のバージョン番号を表示する man ページ通り 非 ASCII 文字列を表示する際に、16 進表記で表 man ページ通り 示する 全ての文字列を表示する際に、16 進表記で表示 man ページ通り する 各システムコールの戻り値を表示する位置(行 -a column man ページ通り man ページ通り の何文字目にするか)を変更する。 デフォルト値は 40 19 どのイベントをどのようにトレースするかを qualifier に指定可能な値 変更する。expr の書式は以下の通り([]で囲ま として以下が存在する。 れた部分は省略可能)。 t :trace と同義 [qualifier=][!]value1[,value2] a :abbrev と同義 v :verbose と同義 x :raw と同義 qualifier の値は、項番 20~31 に後述する -e expr trace、abbrev、verbose、raw、signal、read、 signals:signal と同義 write が指定可能で、デフォルトは trace とな s :signal と同義 っている。 reads :read と同義 例えば、-eopen を指定(-e trace=open と同義) r :read と同義 した場合、open コールのみトレースする。また、 writes :write と同義 -e trace=!open を指定した場合、open 以外の w :write と同義 全システムコールをトレースする。 20 set で指定したシステムコールのみトレースす -e trace=set man ページ通り る。all 及び none も指定可能であり、デフォル トは all 21 22 -e trace=file -e trace=process 23 -e trace=network 24 -e ファイル関連のシステムコールのみトレース man ページ通り する プロセス管理関連のシステムコールのみトレ man ページ通り ースする ネットワーク関連のシステムコールのみトレ man ページ通り ースする シグナル関連のシステムコールのみトレース man ページ通り trace=signal する 25 -e trace=ipc IPC 関連のシステムコールのみトレースする man ページ通り 26 -e abbrev=set set で指定したシステムコールに関して、大き man ページ通り - 3-71 - # オプション man ページ概要 評価結果 な構造体の各メンバを省略して表示する。 all 及び none を指定可能であり、デフォルトは all。abbrev=none は、-v オプションと同義 27 set で指定したシステムコールに関して、構造 -e verbose=set man ページ通り 体の内容(メンバ名と値)を表示する。 all 及び none を指定可能であり、デフォルトは all 28 set で指定したシステムコールの引数と戻り値 -e raw=set man ページ通り の値を、生データとして 16 進表記で表示する。 all 及び none を指定可能 29 set で指定したシグナルのみトレースする。 -e signal=set 30 -e read=set all、none 以外のシグナル all 及び none を指定可能で、 デフォルトは all。 名を指定すると、エラーが 例えば signal=!SIGIO(または signal=!io)を 発生する 指定した場合、SIGIO はトレースしない (Ver 4.5.9 で修正済み) read コールのファイルディスクリプタ値が、 man ページ通り set で指定した値と一致した場合、読み出しデ ータを 16 進表記でダンプ表示する 31 write コールのファイルディスクリプタ値が、 -e write=set man ページ通り set で指定した値と一致した場合、書き込みデ ータを 16 進表記でダンプ表示する 32 -o filename 33 filename で指定したファイルに対し、strace の結果を出力する システムコールの所要時間を計算する際に考 -O overhead man ページ通り man ページ通り 慮される、strace のオーバヘッド(μ秒の単位) を変更する 34 動作中のプロセスにアタッチし、トレースを行 -p pid man ページ通り う。デタッチするには Ctl-c を入力する。デタ ッチによりトレースを終了する(トレース対象 は続行)。 35 -s strsize 36 ファイル名以外の文字列の表示を、指定文字数 man ページ通り で切り詰める。デフォルトは 32 -c オプションで各システムコールの統計情報 man ページ通り を表示する際、sortby で指定した項目でソート -S sortby する。 sortby に指定可能な値は、time、calls、name、 nothing で、デフォルトは time 37 -u username トレース対象プログラムを、username のユーザ 権限で実行する - 3-72 - man ページ通り # 38 オプション -E var=val 39 -E var man ページ概要 評価結果 トレース対象プログラムを実行する際に、環境 man ページ通り 変数の追加および変更(var=val)を行う トレース対象プログラムを実行する際に、var man ページ通り で指定された環境変数を削除する 3.3.3.3 考察 当初の予想では、全オプション問題なく動作し、いくつか man ページにないオプション を確認できるのでは、と考えていた。 評価の結果、確認できた項目は下記の通り。 (1) -f オプションだけで、vfork で生成された子プロセスのトレースが可能 (2) -e signal= オプションだけは正しく動作しない (3) -e expr オプションに関しては、省略形式の別名の指定が可能 (1) に関して、man ページでは vfork で生成された子プロセスのトレースを行うには、-F オプションが必要となっているが、実際には-f オプションだけでトレース可能であった。 (2) の-e signal= オプションに関しては、その後の調査によってバージョン 4.5.9 からは正 しく動作することを確認した。このオプションに関しては、使用頻度が低いために問題が 顕在化しなかったのだと考えられる。逆に考えると、使用頻度の高いオプションを使用す るだけで大半の問題は解決できてきたと考えられ、strace の有用性を物語っていると思わ れる。 3.3.4 strace 信頼性評価(前提条件) strace の信頼性評価として、CPU 負荷、I/O 負荷、メモリ負荷のそれぞれについて、ど の程度の負荷までならば問題なく動作するかを評価した。 strace 信頼性評価の前提条件を、以下に示す。 (1) システムのサービスによって測定誤差が生じるのを防ぐため、使用していないランレベ ル(本評価環境の場合は4)を使い、不要なサービスを全て停止するように設定してお く。今回の評価時に動作するように設定しているサービスは、autofs、syslog、haldaemon、 sysstat、kudzu、lm_sensors、cpuspeed のみ。 (2) 負荷設定直後に計測開始するのではなく、負荷が安定することを確認してから、計測を 開始する。 (3) 自作のマイクロベンチマーク(図 3.3-1)を使用し、1システムコールの所要時間を計 測する。これをstraceありとなしでそれぞれ計測し、その差分をもってstraceのオーバ - 3-73 - ーヘッドとする。 (4) 一般的な利用方法をモデリングするため、strace は ext3 ファイルシステム上にログフ ァイル出力を行うものとする。 (5) システムコールについては、時前計測で異なる傾向が見られた、gettimeofday、getuid、 uname の3つについて、それぞれ計測する。 (6) 評価結果は、評価環境に依存している。環境が変わると、目安となる負荷も変わるので、 注意が必要。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main (int argc, char *argv[]) { struct timeval tv, otv; int sec=10; unsigned long count; if(argc == 2) sec = atoi(argv[1]); gettimeofday(&otv,NULL); count = 0; getuid, uname 用に使用する 場合は、コメントを外してコ ンパイルする do { //getuid(); //uname(NULL); gettimeofday(&tv,NULL); count ++; } while ( count < 1000 ); tv.tv_sec -= otv.tv_sec; tv.tv_usec -= otv.tv_usec; printf("%d nsec per call\n", (tv.tv_sec*1000*1000 + tv.tv_usec)/(count/1000)); return 0; } 図 3.3-1 gettimeofday 用マイクロベンチマークプログラム - 3-74 - 不要なサービスを停止するための手順は、下記の通り。 a. ランレベルの変更 # vi /etc/inittab :(略) # Default runlevel. The runlevels used by RHS are: # 0 - halt (Do NOT set initdefault to this) # 1 - Single user mode # 2 - Multiuser, without NFS (The same as 3, if you do not have networking) # 3 - Full multiuser mode # 4 - unused # 5 - X11 # 6 - reboot (Do NOT set initdefault to this) # この部分を 4(未使用レベル) に変更する id:3:initdefault: :(略) b. レベル4で on になっているサービスの確認 レベル4で on になっている サーピスをチェックする # chkconfig --list rpcsvcgssd 0:off 1:off 2:off 3:on 4:on 5:on 6:off crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off microcode_ctl 0:off 1:off 2:off 3:off 4:off 5:off 6:off :(略) c. 不要なサービス群を off に設定 チェックしたサービス群を OFF にする (図は rpcsvcgssd の例) # chkconfig --level 4 rpcsvcgssd off d. リブート # shutdown -r now e. サービスが正しく設定されていることを確認 off に設定したサービスが、正 レベル4で on になっている しく off になっていることを サーピスをチェックする 確認する # chkconfig --list rpcsvcgssd 0:off 1:off 2:off 3:on 4:off 5:on 6:off crond 0:off 1:off 2:on 3:on 4:off 5:on 6:off microcode_ctl 0:off 1:off 2:off 3:off 4:off 5:off 6:off :(略) - 3-75 - gettimeofday のマイクロベンチマークを strace ありとなしで計測する場合の実行例は、 下記の通り。 a. strace なしで実行 $ gtobench2_gettimeofday 2961 nsec per call b. strace ありで実行 $ strace -o strace.log gtobench2_gettimeofday 33885 nsec per call 各システムコールの所要時間 T(syscall)の算出式は gettimeofday コールかどうかで異な り、マイクロベンチマークで計測した時間を B(syscall)とした場合、下記の通り。 (1) T(gettimeofday)=B(gettimeofday) (2) T(other)=B(other)-B(gettimeofday) 3.3.5 strace 信頼性評価(CPU 負荷時) 3.3.5.1 評価手順 strace 信頼性評価(CPU 負荷)の評価手順を、以下に示す。 (1) マイクロベンチマークプログラムを使い、3つのシステムコールについて、strace のオ ーバーヘッドを 10 点分計測する。 (2) 負荷生成プログラム stress を用いて、CPU 負荷(プロセス数:200)を設定する。 $ stress -c 200 stress 実行後、各 stress プロセスのスケジューリング状態が均等になることを top コ マンドのプライオリティ表示(PR)覧で確認する。 (3) (1)をもう一度行う。この手順によって、CPU 負荷設定時の strace オーバーヘッドを算 出する。 (4) stress の CPU 負荷をプロセス数:400、600、800、1000 と変えて(2)、(3)の手順を繰 り返す。 3.3.5.2 結果と考察 測定結果を 表 3.3-3、表 3.3-4、表 3.3-5 に示す。これらの表より、どのシステムコール の場合でもstraceを介さずに実行した場合はCPU負荷の影響をほとんど受けていないこと が分かる。これは、システムコール 1000 回分の実行が、全て1度のスケジューリング内で 実行されており、その間に他のプロセスがスケジューリングされないためと考えられる。 - 3-76 - 表 3.3-3 gettimeofday コールと strace のオーバーヘッド(CPU 負荷時) 項 CPU 負 システムコールのオーバ strace のオーバーヘッド(usec/コー 番 荷(プロ ーヘッド(usec/コール) ル) セス数) 最小値 最大値 平均値 最小値 最大値 平均値 1 0 0.47 0.50 0.49 99.56 101.57 100.15 2 200 0.47 0.50 0.48 99.82 14,991.35 2,411.68 3 400 0.47 0.50 0.48 99.54 24,713.76 3,067.10 4 600 0.47 0.50 0.49 99.53 56,882.43 8,218.78 5 800 0.47 0.51 0.49 99.70 68,333.59 13,391.28 6 1000 0.47 0.50 0.49 99.01 71,430.01 19,293.51 表 3.3-4 getuid コールと strace のオーバーヘッド(CPU 負荷時) 項 CPU 負 システムコールのオーバ strace のオーバーヘッド(usec/コー 番 荷(プロ ーヘッド(usec/コール) ル) セス数) 最小値 最大値 平均値 最小値 最大値 平均値 1 0 0.23 0.26 0.24 91.50 197.64 193.42 2 200 0.23 0.26 0.25 92.42 2,396.11 1,039.84 3 400 0.23 0.26 0.24 92.72 8,520.23 3,048.17 4 600 0.22 0.25 0.24 93.40 44,998.41 15,576.54 5 800 0.24 0.25 0.25 91.90 80,143.35 33,371.15 6 1000 0.22 0.33 0.25 91.69 114,876.04 44,434.96 表 3.3-5 uname コールと strace のオーバーヘッド(CPU 負荷時) 項 CPU 負 システムコールのオーバ strace のオーバーヘッド(usec/コー 番 荷(プロ ーヘッド(usec/コール) ル) セス数) 最小値 最大値 平均値 最小値 最大値 平均値 1 0 0.69 0.72 0.70 209.21 211.10 210.64 2 200 0.70 0.73 0.71 9,967.25 40,073.87 29,207.73 3 400 0.70 0.73 0.71 27,768.82 78,000.90 59,612.87 4 600 0.69 0.72 0.70 1,885.32 114,959.96 76,587.22 5 800 0.69 0.72 0.70 57,450.17 152,566.38 123,812.39 6 1000 0.69 0.70 0.69 205.38 228,837.63 155,514.37 システムコール毎に、CPU負荷とstraceオーバーヘッドの関係をグラフにしたものを 図 3.3-2、図 3.3-3、図 3.3-4 に示す。 - 3-77 - オーバーヘッド(msec) 250 200 min max avg 150 100 50 0 0 200 オーバーヘッド(msec) 図 3.3-2 800 1000 gettimeofday の strace オーバーヘッド(CPU 負荷時) 250 200 min max avg 150 100 50 0 0 200 図 3.3-3 オーバーヘッド(msec) 400 600 プロセス数 400 600 プロセス数 800 1000 getuid の strace オーバーヘッド(CPU 負荷時) 250 200 min max avg 150 100 50 0 0 200 図 3.3-4 400 600 プロセス数 800 1000 uname の strace オーバーヘッド(CPU 負荷時) - 3-78 - 以上のグラフより、プロセス数が増加するに伴い strace オーバーヘッドも増加する傾向 があることが分かる。 どの程度の CPU 負荷まで strace を問題なく使用できるかの判断としては、下記の理由 により「CPU フル稼働プロセス数が 400 より少なければ使用可能」が一つの目安であると 考えられる。 (1) gettimeofday、getuid の場合、プロセス数 400 を超えると急激にオーバーヘッドが増加。 (2) uname の場合プロセス数 400 でオーバーヘッドの平均が 50msec を超える。 注)ただし、この数値は評価環境に依存した値である。 3.3.6 strace 信頼性評価(I/O 負荷時) 3.3.6.1 評価手順 strace 信頼性評価(I/O 負荷)の評価手順を、以下に示す。 (1) 事前計測として、I/O 負荷が線形に近い形で変化する stress のパラメータを確認する (I/O 負荷は、iostat を5秒間隔で実行することで計測する) 。今回の場合は、下記の負 荷設定~計測方法によって、線形 I/O 負荷が得られた。 ・書き込みバイト数を 256KByte に固定 ・プロセス数を 0~1000 まで 200 刻みに変えて行く ・--hdd-noclean を指定(負荷をかけている間は、生成したファイルを削除しない) ・上記パラメータで stress 実行後、iostat の書き込みスループット表示値の上下動 がある程度安定してから、2 分間計測する この負荷を設定するための stress コマンド(プロセス数 200 の例)を下記に示す。 $ stress --hdd-bytes 256KB --hdd-noclean -hdd 200 (2) 上記と同じ負荷設定~計測方法の間に、マイクロベンチマークプログラムを実行し、3 つのシステムコールについて、strace のオーバーヘッドを計測する。 (3) (2)の計測を繰り返し、10 点分計測する。これをプロセス数 0~1000 まで 200 刻みで行 う。 3.3.6.2 結果と考察 事前に計測した、stressでI/O負荷を設定した際の、書き込みスループットを 表 3.3-6 に 示す。 - 3-79 - 表 3.3-6 stress I/O 負荷時のプロセス数とスループットの関係 項 stress プロセス 番 数 書き込みスループット(KByte/秒) 最小値 最大値 平均値 1 200 279.57 295.95 284.16 2 400 247.20 363.71 295.34 3 600 734.22 1,165.78 928.88 4 800 945.17 1,400.13 1,245.15 5 1000 1,253.02 1,604.74 1,438.19 スループット(MByte/sec) 表 3.3-6 をグラフにしたものを 図 3.3-5 に示す。 2 1.5 min max avg 1 0.5 0 0 図 3.3-5 200 400 600 プロセス数 800 1000 stress I/O 負荷時のプロセス数とスループットのグラフ 多少のばらつきはあるものの、事前計測の目的である、線形の I/O 負荷が得られているこ とが確認できる。 本評価での strace のオーバーヘッドは、I/O 負荷を基準とした計測値を確認する必要が あるが、実際には stress プロセス数を変えて計測している。このため、strace オーバーヘ ッド計測時のプロセス数を、事前に計測したスループットの平均値に変換する。 変換後の計測結果を 表 3.3-7、表 3.3-8、表 3.3-9 に示す。 これらの表から、どのシステムコールの場合も strace を介さずに実行した場合は、I/O 負 荷の影響をほとんど受けていないことが分かる。これは、CPU 負荷の場合と同じ要因によ ると考えられる。 - 3-80 - 表 3.3-7 gettimeofday コールと strace のオーバーヘッド(I/O 負荷時) 項 I/O 負荷(スル システムコールのオーバ strace のオーバーヘッド(usec 番 ープット: ーヘッド(usec/コール) /コール) KByte/秒) 最小値 最大値 平均値 最小値 最大値 平均値 1 0 0.47 0.51 0.49 98.14 98.83 98.51 2 284.16 0.47 0.51 0.49 99.47 100.88 99.86 3 295.34 0.47 0.51 0.49 98.36 29,788.07 3,069.39 4 928.88 0.47 0.50 0.48 98.25 13,719.40 1,461.74 5 1,245.15 0.47 0.50 0.48 97.81 2,940.19 622.62 6 1,438.19 0.47 0.63 0.51 98.75 8,943.56 1,004.99 表 3.3-8 getuid コールと strace のオーバーヘッド(I/O 負荷時) 項 I/O 負荷(スル システムコールのオーバ strace のオーバーヘッド(usec 番 ープット: ーヘッド(usec/コール) /コール) KByte/秒) 最小値 最大値 平均値 最小値 最大値 平均値 1 0 0.71 0.74 0.73 90.92 91.86 91.29 2 284.16 0.71 0.75 0.74 90.42 14,965.79 5,698.87 3 295.34 0.71 0.74 0.73 93.45 9,135.86 12,167.37 4 928.88 0.71 0.74 0.73 94.77 26,121.42 10,914.69 5 1,245.15 0.71 0.74 0.73 6,633.82 115,849.30 63,265.69 6 1,438.19 0.71 0.74 0.73 90.64 93,260.74 49,300.90 表 3.3-9 uname コールと strace のオーバーヘッド(I/O 負荷時) 項 I/O 負荷(スル システムコールのオーバ strace のオーバーヘッド(usec 番 ープット: ーヘッド(usec/コール) /コール) KByte/秒) 最小値 最大値 平均値 最小値 最大値 平均値 1 0 1.18 1.21 1.19 207.14 208.86 207.61 2 284.16 1.18 1.21 1.19 1,258.61 52,662.20 28,635.51 3 295.34 1.18 1.26 1.20 11,777.31 86,316.45 62,966.00 4 928.88 1.18 1.19 1.19 209.05 82,891.10 42,701.96 5 1,245.15 1.18 1.22 1.19 228.78 349,989.48 115,917.87 6 1,438.19 1.18 1.29 1.20 208.78 156,542.47 97,228.24 システムコール毎に、I/O負荷とstraceオーバーヘッドの関係をグラフにしたものを 図 3.3-6、図 3.3-7、図 3.3-8 に示す。 - 3-81 - オーバーヘッド(msec) 400 350 300 250 200 150 100 50 0 min max avg 0 0.25 オーバーヘッド(msec) 図 3.3-6 1.25 1.5 gettimeofday の strace オーバーヘッド(I/O 負荷時) 400 350 300 250 200 150 100 50 0 min max avg 0 0.25 図 3.3-7 オーバーヘッド(msec) 0.5 0.75 1 スループット(MByte/秒) 0.5 0.75 1 スループット(MByte/秒) 1.25 1.5 getuid の strace オーバーヘッド(I/O 負荷時) 400 350 300 250 200 150 100 50 0 min max avg 0 0.25 図 3.3-8 0.5 0.75 1 スループット(MByte/秒) 1.25 1.5 uname の strace オーバーヘッド(I/O 負荷時) - 3-82 - 以上のグラフより、書き込みスループットが 1MByte/秒くらいから、strace オーバーヘ ッドが急増しており、最小値と最大値のばらつきも大きくなっていることが分かる。 よって、どの程度の I/O 負荷まで strace を問題なく使用できるかの判断としては「書き込 みスループットが 1MByte/秒より少なければ使用可能」が一つの目安であると考えられる。 注)ただし、この数値は評価環境に依存した値である。 今回の事前評価では、書き込みデータバイト数を変えても I/O 負荷が線形にならなかった ため、プロセス数を変える方法を採らざるを得なかった。今回の評価で得られた数値には、 プロセス数増加によるスケジューリングのオーバーヘッドも影響を与えている可能性が考 えられるが、このような可能性を排除するためにも、もっと少ないプロセス数で I/O 負荷を 線形に変えられるようなパラメータの設定方法を見つけ、そのパラメータでも評価するこ とが今後の課題である。 3.3.7 strace 信頼性評価(メモリ負荷時) 3.3.7.1 評価手順 strace の使用メモリはそれ程多くないと予想され、スワップアウトする付近までメモリ 負荷を上げないと、strace のオーバーヘッドは変化しないと考えられる。このため、事前 計測を行い、スワップアウトする付近のメモリ負荷を大まかに確認してから、strace のオ ーバーヘッドを測定する。 strace 信頼性評価(メモリ負荷)の評価手順を、以下に示す。 (1) 事前計測として、stress でメモリ負荷を設定(設定方法は後述)した上で、strace 経由 でマイクロベンチマークを実行する。メモリ負荷バイト数を増やしながらこの手順を繰 り返し、スワップアウトが発生する境界のメモリ負荷バイト数を確認する。今回の場合 は、484MByte だった。 ※スワップアウトの発生は、free コマンドで確認する。 (2) stress でメモリ負荷を設定する。stress プロセス数は1とし、確保するメモリ容量は事 前計測で得られたスワップアウト直前の値(今回の場合は 482MByte)を設定する。 $ stress -m 1 --vm-hang --vm-bytes 482MB (3) free コマンドにより、メモリ負荷が安定することを確認する。 (4) マイクロベンチマークを使い、3つのシステムコールについて strace オーバーヘッド を 10 点分計測する。 (5) メモリ負荷を、1MByte ずつ上げながら、(2)~(4)の手順を繰り返す。メモリ負荷を上 げても strace オーバーヘッドにほとんど変化が見られないようならば計測を終了する。 3.3.7.2 結果と考察 測定結果を 表 3.3-10、表 3.3-11、表 3.3-12 に示す。 - 3-83 - 表 3.3-10 gettimeofday コールと strace のオーバーヘッド(メモリ負荷時) 項 メモリ負荷 システムコールのオーバ strace のオーバーヘッド(usec/ 番 (MByte) ーヘッド(usec/コール) コール) 最小値 最大値 平均値 最小値 最大値 平均値 1 482 0.47 0.50 0.49 97.61 133.29 101.74 2 483 0.47 0.51 0.49 97.61 98.26 97.94 3 484 0.47 0.51 0.48 97.61 100.21 98.99 4 485 0.47 0.51 0.48 97.70 99.04 98.28 5 486 0.47 0.51 0.48 97.83 100.08 98.85 表 3.3-11 getuid コールと strace のオーバーヘッド(メモリ負荷時) 項 メモリ負荷 システムコールのオーバ strace のオーバーヘッド(usec/ 番 (MByte) ーヘッド(usec/コール) コール) 最小値 最大値 平均値 最小値 最大値 平均値 1 482 0.23 0.26 0.25 90.58 76.97 89.51 2 483 0.22 0.25 0.24 90.71 120.86 93.80 3 484 0.23 0.26 0.25 92.26 5,150.03 597.60 4 485 0.24 0.26 0.25 91.11 91.98 91.36 5 486 0.23 0.27 0.25 89.95 89.40 89.65 表 3.3-12 uname コールと strace のオーバーヘッド(メモリ負荷時) 項 メモリ負荷 システムコールのオーバ strace のオーバーヘッド(usec/ 番 (MByte) ーヘッド(usec/コール) コール) 最小値 最大値 平均値 最小値 最大値 平均値 1 482 0.70 0.72 0.70 203.92 413.35 225.34 2 483 0.69 0.72 0.70 203.44 225.51 207.06 3 484 0.70 0.73 0.72 205.46 2,490.64 435.01 4 485 0.70 0.73 0.71 206.47 209.74 207.86 5 486 0.70 0.73 0.71 206.16 206.73 206.81 これらの表から、どのシステムコールの場合も strace を介さずに実行した場合は、メモ リ負荷の影響をほとんど受けていないことが分かる。これは、CPU 負荷の場合と同じ要因 によると考えられる。 システムコール毎に、 メモリ負荷とstraceオーバーヘッドの関係をグラフにしたものを 図 3.3-9、図 3.3-10、図 3.3-11 に示す。 - 3-84 - オーバーヘッド(msec) 6 5 4 min max avg 3 2 1 0 482 483 オーバーヘッド(msec) 図 3.3-9 485 486 gettimeofday の strace オーバーヘッド(メモリ負荷時) 6 5 4 min max avg 3 2 1 0 482 483 図 3.3-10 オーバーヘッド(msec) 484 メモリ負荷(MByte) 484 メモリ負荷(MByte) 485 486 getuid の strace オーバーヘッド(メモリ負荷時) 6 5 4 min max avg 3 2 1 0 482 483 図 3.3-11 484 メモリ負荷(MByte) 485 486 uname の strace オーバーヘッド(メモリ負荷時) - 3-85 - これらのグラフから、strace のオーバーヘッドはスワップアウト発生時のみ約 5msec と 多少大きくなるが、スワップアウトの前後ではほとんど一定(1msec 以下)のオーバーヘ ッドしかかからないことが分かる。 メモリスワップアウト発生後のオーバーヘッドが少ないことについては、今回の評価は メモリ負荷が安定してから計測する方法のため、スワップアウト後ではメモリに strace 使 用分程度の空きがあったためではないかと考えられる。 いずれにせよ、strace のオーバーヘッドは最大でも約 5msec、平均では 1msec 以下とな っており、strace を使用する際には、メモリ負荷はほとんど考慮しなくても良いと考えら れる。 注)ただし、この数値は評価環境に依存した値である。 - 3-86 - 3.4 ネットワーク情報収集ツールの評価 ネットワーク情報収集ツールとして ping, traceroute, netstat, ifconfig, ethtool の機能評 価を行なうことにする。 3.4.1 ツールの使用方法 H/W 監視ツールとして、ethtool の機能検証を、インターフェース監視ツールとして、 ifconfig, netstat の機能検証を、経路監視として、ping, traceroute,を、システムの監視と して、swatch の機能検証 を行なうことにする。また、ネットワークの障害発生時のデータ 転送の影響を回避する方法として、ネットワークの冗長化機能の検証を行なう。 3.4.1.1 ethtool ethtools は、ネットワーク機器の物理/電気リンクの状態を検出するコマンドである。実 行は ethtool を実行する。パラメータに、イーサネットデバイス名を指定することで状態を 監視するデバイスを指定する事ができる。以下に書式例は、eth1 の稼動情報を表示した結 果である。 ethtool ethX ethtool -h ethtool -a ethX ethtool -A ethX [autoneg on|off] [rx on|off] [tx on|off] ethtool -c ethX ethtool -C ethX [adaptive-rx on|off] [adaptive-tx on|off] [rx-usecs N] [rx-frames N] [rx-usecs-irq N] [rx-frames-irq N] [tx-usecs N] [tx-frames N] [tx-usecs-irq N] [tx-frames-irq N] [stats-block-usecs N] [pkt-rate-low N] [rx-usecs-low N] [rx-frames-low N] [tx-usecs-low N] [tx-frames-low N] [pkt-rate-high N] [rx-usecs-high N] [rx-frames-high N] [tx-usecs-high N] [tx-frames-high N] [sample-interval N] ethtool -g ethX ethtool -G ethX [rx N] [rx-mini N] [rx-jumbo N] [tx N] ethtool -i ethX ethtool -d ethX ethtool -e ethX [raw on|off] [offset N] [length N] ethtool -E ethX [magic N] [offset N] [value N] ethtool -k ethX ethtool -K ethX [rx on|off] [tx on|off] [sg on|off] [tso on|off] ethtool -p ethX [N] ethtool -r ethX ethtool -S ethX - 3-87 - ethtool -t ethX [offline|online] ethtool -s ethX [speed 10|100|1000] [duplex half|full] [port tp|aui|bnc|mii] [autoneg on|off] [phyad N] [xcvr internal|external] [wol p|u|m|b|a|g|s|d...] [sopass xx:yy:zz:aa:bb:cc] [msglvl N] 図 3.4-1 ethtool 書式 表 3.4-1 ethtool オプション -a queries the specified ethernet device for pause parameter information. -A change the pause parameters of the specified ethernet device. autoneg on|off Specify if pause autonegotiation is enabled. rx on|off Specify if RX pause is enabled. / Specify if RX checksumming is enabled. tx on|off Specify if TX pause is enabled. / Specify if TX checksumming is enabled. -c queries the specified ethernet device for coalescing information. -C change the coalescing settings of the specified ethernet device. -g queries the specified ethernet device for rx/tx ring parameter information. -G change the rx/tx ring parameters of the specified ethernet device. rx N Change number of ring entries for the Rx ring. rx-mini N Change number of ring entries for the Rx Mini ring. rx-jumbo N Change number of ring entries for the Rx Jumbo ring. tx N Change number of ring entries for the Tx ring. -i queries the specified ethernet device for associated driver information. -d retrieves and prints a register dump for the specified ethernet device. -e retrieves and prints an EEPROM dump for the specified ethernet device. -E Changes EEPROM byte for the specified ethernet device. -k queries the specified ethernet device for offload information. sg on|off Specify if scatter-gather is enabled. tso on|off Specify if tcp segmentation offload is enabled. -p initiates adapter-specific action intended to enable an operator to easily identify the adapter by sight. N Length of time to perform phys-id, in seconds. -r restarts auto-negotiation on the specified ethernet device, if auto-negotiation is enabled. -S queries the specified ethernet device for NIC- and driver-specific statistics. speed 10|100|1000 Set speed in Mb/s. duplex half|full Set full or half duplex mode. port tp|aui|bnc|mii Select device port. autoneg on|off Specify if autonegotiation is enabled. phyad N PHY address. - 3-88 - xcvr Select transceiver type. internal|external wol p Wake on phy activity p|u|m|b|a|g|s|d... u Wake on unicast messages m Wake on multicast messages b Wake on broadcast messages a Wake on ARP g Wake on MagicPacket(tm) s Enable SecureOn(tm) password for MagicPacket(tm) d sopass Disable (wake on nothing). This option clears all previous options. Set the SecureOn(tm) password. xx:yy:zz:aa:bb:cc msglvl N Set the driver message level. Meanings differ per driver. # ethtool eth1 Settings for eth1: Supported ports: [ TP MII ] Supported link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full Supports auto-negotiation: Yes Advertised link modes: 10baseT/Half 10baseT/Full 100baseT/Half 100baseT/Full Advertised auto-negotiation: Yes Speed: 100Mb/s Duplex: Full Port: MII PHYAD: 1 Transceiver: internal Auto-negotiation: on Supports Wake-on: g Wake-on: d Current message level: 0x00000007 (7) Link detected: yes 図 3.4-2 ethtool 実行例 3.4.1.2 ifconfig インターフェースの状態確認/設定のためのコマンドであり、IP アドレス,サブネットマ - 3-89 - スクの確認や設定をすることができる。以下に、書式、オプション、実行例を記す。実行 例では、bonding を使用して、ネットワークの冗長化がなされている bonding を使用した 場合の ifconfig の実結果である。 ifconfig [interface] ifconfig interface [aftype] options | address ... 表 3.4-2 ifconfig 書式 表 3.4-3 ifconfig 使用できるオプション interface ドライバの名前に装置の番号を付けたもの up インタフェースを活動状態にする down インタフェースのドライバを停止する [-]arp ARP プロトコルの使用を有効/無効にする [-]promisc 無差別 (promiscuous) モードを有効/無効にする [-]allmulti 全マルチキャストモードを有効/無効にする metric N インタフェースメトリックを設定する mtu N インタフェースの最大転送単位 (MTU) を設定する dstaddr addr ポイント間接続においてリモートの IP アドレスを設定する netmask addr ネットワークマスクを設定する add addr/prefixlen IPv6 アドレスをインタフェースに追加する del addr/prefixlen IPv6 アドレスをインタフェースから削除する tunnel xx.xx.xx.xx 新規の SIT (IPv6-in-IPv4) デバイスを作成し、 与えられた対象アドレスにトンネ ルする irq addr デバイスにより使用される割り込みを設定する io_addr addr デバイスの I/O 開始アドレスを設定する mem_start addr デバイスにより使用される共有メモリーの開始アドレスを設定する media type デバイスで使用される、物理ポートもしくは媒体タイプを設定する [-]broadcast [addr] アドレスを指定すると、このインタフェースに プロトコルブロードキャストアド レスを設定する [-]pointopoint [addr] ポイント間接続モードを有効にする hw class address デバイスドライバーがこの操作をサポートしていれば、 インタフェースのハード ウェアアドレスを設定する multicast インタフェースのマルチキャストフラグを設定する txqueuelen length デバイスの送信キューの長さをセットする # ifconfig bond0 Link encap:Ethernet HWaddr 00:12:3F:6E:75:9E inet addr:172.16.37.141 Bcast:172.16.39.255 - 3-90 - Mask:255.255.252.0 UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1 RX packets:2895740 errors:0 dropped:0 overruns:0 frame:0 TX packets:2440459 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:367358753 (350.3 Mb) eth0 Link encap:Ethernet TX bytes:408660326 (389.7 Mb) HWaddr 00:12:3F:6E:75:9E UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:1481442 errors:0 dropped:0 overruns:0 frame:0 TX packets:1221730 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:192590856 (183.6 Mb) TX bytes:217084785 (207.0 Mb) Interrupt:18 Memory:dfcf0000-dfd00000 eth1 Link encap:Ethernet HWaddr 00:12:3F:6E:75:9E UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:1414298 errors:0 dropped:0 overruns:0 frame:0 TX packets:1218729 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:174767897 (166.6 Mb) lo TX bytes:191575541 (182.7 Mb) Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:4347 errors:0 dropped:0 overruns:0 frame:0 TX packets:4347 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:376568 (367.7 Kb) TX bytes:376568 (367.7 Kb) 図 3.4-3 ifconfig 実行例 3.4.1.3 netstat netstat ネットワーク機器までのルーティング情報などを取得することができるコマンド である。オプションによっては、インターフェイスごとのネットワーク統計などを確認す ることができる。実行例は、オプションに -nr を指定し、出力を IP アドレスなど数値のみ に抑制し、ルーティング・テーブルを表示している。 netstat [address_family_options] [--tcp|-t] [--udp|-u] [--raw|-w] [--listening|-l] - 3-91 - [--all|-a] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--symbolic|-N] [--extend|-e[--extend|-e]] [--timers|-o] [--program|-p] [--verbose|-v] [--continuous|-c] [delay] netstat {--route|-r} [address_family_options] [--extend|-e[--extend|-e]] [--verbose|-v] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--interfaces|-i} [--program|-p] [iface] [--all|-a] [--numeric|-n] [--extend|-e[--extend|-e]] [--verbose|-v] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--groups|-g} [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--masquerade|-M} [--extend|-e] [--numeric|-n] [--numeric-hosts][--numeric-ports][--numeric-ports] [--continuous|-c] [delay] netstat {--statistics|-s} [--tcp|-t] [--udp|-u] [--raw|-w] [delay] address_family_options: [--protocol={inet,unix,ipx,ax25,netrom,ddp}[,...]] [--unix|-x] [--inet|--ip] [--ax25] [--ipx] [--netrom] [--ddp] 図 3.4-4 netstat 書式 表 3.4-4 netstat オプション 引数なし オープンされているソケットの一覧を表示する --route , -r カーネルの経路テーブルを表示する --groups , -g マルチキャストグループメンバーシップ情報を表示する --interface=iface , -i ネットワークインターフェースの状態テーブルを表示する --masquerade , -M マスカレードされた接続を表示する --statistics , -s 各プロトコルの統計情報の一覧を表示する --verbose , -v 詳細表示モードになり、起こっていることをユーザーに知らせる --numeric , -n ホスト・ポート・ユーザーなどの名前を解決せずに、 数字のアドレスで表示する --numeric-hosts ホストアドレスを数値で表示する --numeric-ports ポート番号を数値で表示する --numeric-users ユーザー ID を数値で表示する --protocol=family , -A 接続状態を表示するアドレスファミリーを指定する - 3-92 - -c, --continuous 指定された情報を 1 秒ごとに表示し続ける -e, --extend 詳しい情報を表示する -o, --timers ネットワーキングタイマーに関する情報が追加される -p, --program 各ソケットが属しているプログラムの PID と名前が表示される -l, --listening 接続待ち (listen) 状態にあるソケットのみを表示する -a, --all 接続待ち状態にあるソケットも、 接続待ち状態にないソケットも表示する -F FIB からの経路情報を表示する -C 経路キャッシュからの経路情報を表示する # netstat -nr Kernel IP routing table Destination 192.168.10.0 Gateway 0.0.0.0 127.0.0.0 0.0.0.0 0.0.0.0 192.168.10.1 Genmask Flags 255.255.252.0 255.0.0.0 U U 0.0.0.0 MSS Window 0 0 0 0 UG 0 0 irtt Iface 0 bond0 0 lo 0 bond0 図 3.4-5 netstat 実行例 3.4.1.4 ping ping は ICMP の ECHO_REQUEST パケットをネットワーク上の任意のホストに送 信し、その応答(ICMP ECHO REPLAY)を受け取ることにより、リモートホストとの通 信が可能かどうかを確認するための手段として利用できるコマンドである。ping を実行す る場合、パラメータとして、IP アドレスもしくは、ホスト名(FQDN)を指定する。 ping [ -LRUbdfnqrvVaAB] [ -c count] [ -i interval] [ -l preload] [-p pattern] [ -s packetsize] [ -t ttl] [ -w deadline] [ -F flowlabel] [ -I interface] [ -M hint] [ -Q tos] [ -S sndbuf] [ -T timestamp option] [ -W timeout] [ hop ...] destination 図 3.4-6 ping 書式 表 3.4-5 ping オプション -c count cont 個のパケットを送信した後、停止する -d 使用するソケットに SO_DEBUG オプションを設定する -i wait 個々のパケットの間に wait 秒待つ -l preload 指定した preload の値だけ ECHO_REQUEST パケットを出来るだけ速く送信し、 通常の動作に戻る -n 数値出力のみ - 3-93 - -p pattern 送出するパケットを埋めるための 16 個までの “pad”バイトを指定できる -q 開始と終了時の要約以外は、何も表示しない -r 経路を記録する -s packetsize 何バイトのデータが送られるかを指定する -v ECHO_RESPONSE 以外の ICMP パケットを表示する -w waittime ping を waittime 秒後に終了させる -I interface 与えられたインタフェースから、マルチキャストパケットを送る -L マルチキャストパケットのループバックを抑制する -t ttl マルチキャストパケットの IP 寿命時間 (Time To Live) を設定する $ ping www.turbolinux.co.jp PING www.turbolinux.co.jp (xxx. xx. xxx xxx) from xxx. xxx. xx. xxx : 56(84) bytes of data. 64 bytes from www.turbolinux.co.jp (xxx.xx.xxx.xxx): icmp_seq=0 ttl=246 time=344.910 msec 64 bytes from www.turbolinux.co.jp (xxx.xx.xxx.xxx): icmp_seq=1 ttl=246 time=441.273 msec 64 bytes from www.turbolinux.co.jp (xxx.xx.xxx.xxx): icmp_seq=2 ttl=246 time=350.848 msec 64 bytes from www.turbolinux.co.jp (xxx.xxxxxx.xxx): icmp_seq=3 ttl=246 time=177.361 msec 64 bytes from www.turbolinux.co.jp (xxx.xx.xxx.xxx): icmp_seq=4 ttl=246 time=335.683 msec 64 bytes from www.turbolinux.co.jp (xxx.xx.xxx.xxx): icmp_seq=5 ttl=246 time=338.347 msec 64 bytes from www.turbolinux.co.jp (xxx.xx.xxx.xxx): icmp_seq=6 ttl=246 time=312.197 msec --- www.turbolinux.co.jp ping statistics --7 packets transmitted, 7 packets received, 0% packet loss round-trip min/avg/max/mdev = 177.361/328.659/441.273/72.454 ms 図 3.4-7 ping 実行例 3.4.1.5 traceroute traceroute は相手先の機器までのネットワークの経路を調査することができる。ゲート ウェイ-ホスト間や経路上のルータのルーティング設定を確認するために用いられることが 多い。目的のホストまでの経路や疎通が何処までできているか、設置場所が不明なホスト のおおまかな場所を推測する、といった用途にも使用できる。コンソールから traceroute を実行する。パラメータとして、IP アドレスもしくはホスト名(FQDN)を指定する。 traceroute [ -dFInrvx ] [ -f first_ttl ] [ -g gateway ] [ -i iface ] [ -m max_ttl ] [ -p port ] [ -q nqueries ] [ -s src_addr ] [ -t tos ] [ -w waittime ] [ -z pausemsecs ] host [ packetlen ] 図 3.4-8 traceroute 書式 - 3-94 - 表 3.4-6 traceroute オプション -f 使用する TTL の初期値を指定する -F IP パケットの分割を禁止する -d デバックモードで動作する -g 経由すべきゲートウェイのアドレスを最大 8 個まで指定できる。 -i 指定されたインターフェイスを用いて実行する -I UDP パケットではなく、ICMP Echo Request を用いる -m 使用する TTL の最大値を指定する -n 出力を IP アドレスのみに抑制する -p 使用する UDP パケットのポート番号を指定する -r 直接パケットを指定したホストに転送するように指示する -s 指定された IP アドレスから実行する -t パケットのサービスタイプを指定された値に設定する -v 詳細モード -w タイムアウト時間を指定する -x ICMP の CheckSum の評価を行う # traceroute www.ipa.go.jp traceroute to www.ipa.go.jp (xxx.xx.xxx.xxx), 30 hops max, 38 byte packets 1 ns (xxx.xx.xxx.xxx) 0.204 ms 0.166 ms 0.345 ms 2 h18hohoge.net (xxx.xx.xxx.xxx) 3 203.hogehoge.net (xxx.xx.xxx.xxx) 3.074 ms 2.900 ms 2.828 ms 4 163hoge.hoge.net (xxx.xx.xxx.xxx) 3.702 ms 3.252 ms 10.599 ms 5 ae.hoge.net (xxx.xx.xxx.xxx) 6 xxx.xx.xxx.xxx (xxx.xx.xxx.xxx) 7 g2.hogehoge.net (xxx.xx.xxx.xxx) 4.146 ms 4.140 ms 8 g0.hogehoge.net (xxx.xx.xxx.xxx) 4.580 ms 14.806 ms 9 xxx.xx.xxx.xxx (xxx.xx.xxx.xxx) 62.259 ms 5.391 ms 1.528 ms 4.409 ms 0.645 ms 3.785 ms 4.076 ms 10.970 ms 3.669 ms 4.406 ms 10.604 ms 4.137 ms 14.330 ms 4.485 ms 図 3.4-9 traceroute 実行例 3.4.2 bonding 環境での機能評価 3.4.2.1 ハードウェア構成 Bonding 構成を作成するにあたり、2 枚以上のイーサネットカードが必要になる。今回使 用した検証環境を以下に示す。 - 3-95 - 表 3.4-7 ハードウェア環境 CPU Pentium4 3.20GHz メモリ 256MB ハードディスク 160GB ネットワーク Intel Corp. 82557/8/9 [Ethernet Pro 100] x 2 3.4.2.2 ソフトウェア構成 Kernel2.6 を採用している Turbolinux 10 Server を使用して評価を行なった。使用した ソフトウェア構成を示す。 表 3.4-8 ソフトウェア構成 ディストリビューション Turbolinux 10 Server kernel 2.6.8-5 ping(net-tools) 1.60-13 traceroute 1.4a12-3 netstat(net-tools) 1.60-13 ifconfig(net-tools) 1.60-13 ethtool 1.8.2 swatch 3.1.1-1 bonding ドライバ 2.6.0 e100 ドライバ 3.4.10 3.4.2.3 bonding 環境構築 bonding とは、ネットワークを冗長化する機能である。1 つのシステムに複数(2 つ以上) のネットワークインターフェースカードを実装し、両インターフェースより送受信を行な う。ネットワーク機器に障害が起きた場合、別の経路を利用することにより、通信の切断 を回避することができる。bonding 環境を構築する為の設定を以下に示す。 はじめに、modules.confの修正を行なう。図 3.4-10 の内容を追記する。 また、別表にある、オプションを指定する設定を行う。 alias bond0 bonding options bonding mode=0 miimon=100 (mode=0 (ラウンドロビン) で、miimon (切断監視) を 100ms) 図 3.4-10 modules.conf(抜粋) - 3-96 - 表 3.4-9 bonding で使用できるオプション arp_interval ARP モニタリング頻度をミリ秒単位で指定する arp_ip_target arp_interval が正数の場合の IP アドレスを指定する downdelay リンク失敗が検知されてからリンクを無効にするまでの遅延時間をミリ秒で指定する lacp_rate 802.3ad モードでの LACPDU パケットを転送する為のリンクパートナーを問い合わ せる際のレートを指定する。指定可能オプションは別表(lacp_rate で指定できるオプシ ョン)を参照 max_bonds 結合ドライバの1実体用に作成する結合インターフェースの数を指定する miimon MII リンク監視を行う頻度をミリ秒単位で指定する mode 結合ポリシーの1つを指定する。デフォルトはラウンドロビン 指定可能オプションは別表(mode で指定できるオプション)を参照 multicast マルチキャストサポートの為の操作モードを指定する primary この値が入力され、デバイスがオンラインであれば、そのデバイスは出力メディアとし て最初に使用できる updelay リンクアップ状態を検知した後にリンクが有効になるまでの遅延時間をミリ秒で指定す る use_carrier リ ン ク 状 態 を 検 知 す る の に miimon が MII あ る い は ETHTOOL ioctl / netif_carrier_ok() を使うか使わないかを指定する 表 3.4-10 lacp_rate で指定できるオプション slow or 0 LACPDU を送るパートナーを 30 秒単位で要求する (デフォルト) fast or 1 LACPDU を送るパートナーを 1 秒単位で要求する - 3-97 - 表 3.4-11 mode で指定できるオプション balance-rr or 0 ラウンドロビンポリシー 利用可能なスレーブを最初から 最後まで順番に使用して送信する active-backup or 1 アクティブ 結合インターフェース中の1スレーブのみアクティ バックアップポリシー ブとなる。アクティブスレーブでの通信が失敗した時 に限り、他のスレーブがアクティブになる balance-xor or 2 XOR ポリシー (宛先 MAC アドレスで XOR された元 MAC アド レス) モジューラスレーブカウント」を基にして送信 する broadcast or 3 ブロードキャストポリシー 全スレーブインターフェースで全てのパケットを送 信する 802.3ad or 4 IEEE 802.3ad 動的リンク集合。スピードと全/半二 - 重設定が同じ集合グループを作成する 表 3.4-12 multicast で指定できるオプション disabled or 0 無効 (マルチキャストサポートなし) active or 1 アクティブバックアップモードに便利な、 アクティブなスレーブのみ有効とする all or 2 全てのスレーブで有効とする modules.conf の修正後、depmod コマンドにて、起動時に読み込まれるモジュール情報の 更新を行なう。 # depmod –a 図 3.4-11 depmod コマンド bonding インターフェースを作成する為に、/etc/sysconfig/network-scripts に ifcfg-bond0 を作成する。以下に bond0 の設定例を提示する。 DEVICE=bond0 IPADDR=172.16.37.141(142) NETMASK=255.255.252.0 NETWORK=172.16.36.0 BROADCAST=172.16.39.255 BOOTPROTO=none ONBOOT=yes USERCTL=yes 図 3.4-12 bond0 設定 - 3-98 - bond0 インターフェースをマスタとするために、ifcfg-eth0,1 には、スレーブの設定を行う 必要がある為、設定を変更する。 表 3.4-13 インターフェース設定変更 eth0 eth1 # vi ifcfg-eth0 # vi ifcfg-eth1 DEVICE=eth0 DEVICE=eth1 BOOTPROTO=none BOOTPROTO=none MASTER=bond0 MASTER=bond0 SLAVE=yes SLAVE=yes ONBOOT=yes ONBOOT=yes USERCTL=yes USERCTL=yes 設定終了の後、システムを再起動し、bonding環境が稼動することを確認する。再起動後に、 ifconfigコマンドにて、bonding環境が構成されているか確認する。bondingドライバが起動 時にkernelに読み込まれると、図 3.4-13 のような情報が表示される。 # ifconfig bond0 Link encap:Ethernet HWaddr 00:12:3F:6E:75:9E inet addr:172.16.37.141 Bcast:172.16.39.255 UP BROADCAST RUNNING MASTER MULTICAST Mask:255.255.252.0 MTU:1500 Metric:1 RX packets:4753870 errors:0 dropped:0 overruns:0 frame:0 TX packets:4946251 errors:3 dropped:0 overruns:0 carrier:3 collisions:0 txqueuelen:0 RX bytes:470374210 (448.5 Mb) eth0 Link encap:Ethernet TX bytes:868100041 (827.8 Mb) HWaddr 00:12:3F:6E:75:9E UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:1501071 errors:0 dropped:0 overruns:0 frame:0 TX packets:2473063 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:166320363 (158.6 Mb) TX bytes:2593576762 (2473.4 Mb) Interrupt:18 Memory:dfcf0000-dfd00000 eth1 Link encap:Ethernet HWaddr 00:12:3F:6E:75:9E UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3252799 errors:0 dropped:0 overruns:0 frame:0 TX packets:2473189 errors:3 dropped:0 overruns:0 carrier:3 collisions:0 txqueuelen:1000 RX bytes:304053847 (289.9 Mb) TX bytes:2569490729 (2450.4 Mb) 図 3.4-13 構成確認 - 3-99 - 詳細は、/usr/src/linux-2.6.8/Documentation/networking/bonding.txt を参照すること。 3.4.2.4 swatch swatch は、ログを監視し、設定した文字列を検出すると、指定したユーザへメールにて 通知を行う。以下に、swatch のインストール方法を示す。 swatch を使用するには以下の パッケージが必要となる。 perl-Carp-Clan, perl-Bit-Vector, perl-Date-Calc, perl-File-Tail, perl-TimeDate, perl-Date-Manip, perl-Mail-Sendmail 上記パッケージのインストールが終了した後に、swatch のインストールを行なうことがで きる。 # rpm –ivh swatch-3.1.1-1.noarch.rpm 図 3.4-14 swatch のインストール swatch.conf にて、監視対象から検出する文字列の設定、検出時の動作を設定する。下図 “swatch.conf 設定例(抜粋)” は設定例である。 # less swatch.conf watchfor /eth/ <- watchforの後に検出する文字列(パターン)を記述 mail=root <- 指定されたアドレスにメールを送信 throttle use=message <- 一度検出されたパターンが再度検出された場合、 検出を抑えることができる watchfor /hda/ mail=root throttle use=message watchfor /sda/ mail=root throttle use=message 図 3.4-15 swatch.conf 設定例(抜粋) 表 3.4-14 アクションで指定できるパラメータ echo [modes] ターミナルにメッセージを表示する modes により表示形式(別表参照)を変更可能する bell [N] beep 音を N 回鳴らす 数字を指定しなければ 1 回鳴らす - 3-100 - exec command 指定したコマンドを実行する mail [=address:address:…] 指定されたアドレスにメールを送信する [,subject=your_text_here] pipe command[,keep_open] パイプでコマンドに結果を渡す write [user:user:…] swatch を実行しているサーバにログインしているユーザーに、 write コマンドを使用して結果を送信する throttle hours:minutes:seconds 一度検出されたパターンが再度検出された場合、検出を抑える ,[use=message|regex] continue マッチするパターンが検出されると指定されたアクションが実行さ れて終了するが、continue が指定されている場合はさらにマッチする パターンの検出を行なう マッチするパターンを検出すると swatch が終了する quit 表 3.4-15 modes で使用できるオプション normal 通常の表示 bold 太字で表示 underscore 下線で表示 blink 点滅で表示 inverse 反転して表示 [color] black, red, green, yellow, blue, magenta, cyan, white の色で表示 [color_h] black_, red_h, green_h, yellow_h, blue_h, magenta_h, cyan_h, white_h の色で反転 random 上記のものをランダムに使用 設定終了の後、swatch を実行する。 # swatch -c /etc/swatch.conf -t /var/log/messages *** swatch version 3.1.1 (pid:26195) started at Mon Sep 19 02:17:27 JST 2005 図 3.4-16 swatch の実行 表 3.4-16 swatch 起動時に指定できるオプション --config-file=filename -c filename 設定ファイルを指定する --input-record-separator 改行コードの指定する =regular_expression --restart-time -r [+]hh:mm[am|pm] swatch を再起動する時間を hh:mm で指定する =[+]hh:mm[am|pm] --script-dir swatch を起動すると - 3-101 - =/path/to/directory --tail-file スクリプトファイルが作成される -t filename 監視対象となるログのファイル名を指定する -p command コマンドの実行結果を swatch にパイプする -f filename 設定ファイルに適合する内容をスキャンする =filename --read-pip e=command --examine =filename --dump-script[=filename] デバッグ用のオプション 3.4.3 bonding 機能検証手順 bonding 環境下において、ネットワークケーブルが断絶した場合の OS の挙動を調べる事 とする。機能検証の手順として以下を行なう。 ・scp コマンドにて、ファイル転送中に bonding 環境のうち、1 本のネットワークケーブ ルを抜く ・scp のスループットの変化を確認 ・抜いたネットワークケーブルを元に戻し、scp のスループットの変化を確認 3.4.4 bonding 機能検証結果と考察 ケーブルを抜いた直後、スループットが低下するがネットワークの冗長化環境で転送して いる為に、ファイル転送自体が停止する事はない。同状態から、ネットワークケーブルを 戻すことにより、スループットがケーブルを抜く前と同等の値に戻る事も確認できた。 # scp bondtrancefarfile root@dhcp-148:/root bondtrancefarfile 12% 562MB 2.4MB/s 26:44 ETA bondtrancefarfile 12% 564MB 2.4MB/s 27:03 ETA bondtrancefarfile 12% 567MB 2.3MB/s 27:20 ETA bondtrancefarfile 12% 569MB 2.3MB/s 27:35 ETA bondtrancefarfile 12% 571MB 2.3MB/s 27:22 ETA bondtrancefarfile 13% 573MB 2.3MB/s 27:24 ETA bondtrancefarfile 2.1MB/s から、1.9MB/s へ転送量が減る。 13% 573MB 2.1MB/s 30:27 ETA bondtrancefarfile と同時に、転送時間が増えていることもわかる。 13% 574MB 1.9MB/s 33:27 ETA bondtrancefarfile Î 障害が発生した事がわかる。 13% 575MB 1.8MB/s 35:06 ETA bondtrancefarfile 以降、転送量が減り続ける。 13% 576MB 1.7MB/s 36:45 ETA bondtrancefarfile 13% 576MB 1.6MB/s 39:14 ETA bondtrancefarfile 13% 577MB 1.6MB/s 40:40 ETA bondtrancefarfile 13% 578MB 1.5MB/s 42:25 ETA bondtrancefarfile 13% 579MB 1.5MB/s 43:30 ETA bondtrancefarfile 13% 580MB 1.4MB/s 44:57 ETA bondtrancefarfile 13% 581MB 1.4MB/s 46:30 ETA == 省略 == - 3-102 - bondtrancefarfile 13% 590MB 1.1MB/s 56:17 ETA bondtrancefarfile 13% 591MB 1.1MB/s 58:29 ETA bondtrancefarfile 13% 592MB 1.1MB/s 59:54 ETA bondtrancefarfile 13% 593MB 1.1MB/s 1:00:23 ETA bondtrancefarfile 13% 594MB 1.0MB/s 1:01:33 ETA bondtrancefarfile 13% 595MB 1.0MB/s 1:03:06 ETA bondtrancefarfile 13% 595MB 1.0MB/s 1:04:58 ETA bondtrancefarfile 13% 596MB 986.5KB/s 1:05:57 ETA bondtrancefarfile 13% 597MB 958.7KB/s 1:07:51 ETA bondtrancefarfile 13% 598MB 964.4KB/s 1:07:26 ETA bondtrancefarfile 13% 599MB 954.8KB/s 1:08:05 ETA 14% 647MB 907.6KB/s 1:10:43 ETA 14% 648MB 903.6KB/s 1:11:01 ETA 14% 649MB 917.3KB/s 1:09:56 ETA bondtrancefarfile 14% 650MB 908.7KB/s 1:10:35 ETA bondtrancefarfile 14% 652MB 982.7KB/s 1:05:14 ETA bondtrancefarfile 14% 654MB 1.2MB/s 54:24 ETA bondtrancefarfile 14% 657MB 1.3MB/s 48:21 ETA bondtrancefarfile 14% 660MB 1.5MB/s 42:04 ETA bondtrancefarfile 15% 663MB 1.6MB/s 39:03 ETA bondtrancefarfile 15% 681MB 2.0MB/s 31:23 ETA bondtrancefarfile 15% 683MB 2.0MB/s 30:34 ETA bondtrancefarfile 15% 686MB 2.1MB/s 29:40 ETA bondtrancefarfile 15% 689MB 2.2MB/s 28:31 ETA bondtrancefarfile 15% 691MB 2.2MB/s 27:57 ETA bondtrancefarfile 15% 694MB 2.3MB/s 26:56 ETA bondtrancefarfile 15% 697MB 2.3MB/s 26:36 ETA bondtrancefarfile 状態が復旧したと思われる。 bondtrancefarfile 理由は、転送量が障害前と同等の転送量に戻っ bondtrancefarfile た。 15% 699MB 2.4MB/s 26:07 ETA 15% 702MB 2.4MB/s 25:46 ETA 15% 705MB 2.5MB/s 25:04 ETA bondtrancefarfile 16% 708MB 2.5MB/s 24:57 ETA bondtrancefarfile 16% 710MB 2.5MB/s 24:43 ETA == 省略 == 抜いたケーブルを戻した。 bondtrancefarfile 転送量が約 1MB/s から、1.2MB に bondtrancefarfile 上がっていることがわかる。 bondtrancefarfile == 省略 == 図 3.4-17 scp による転送ログ * bondtrancefarfile:転送テストのために作成したランダムなバイナリファイル 4.3Gb を 使用する。 - 3-103 - bonding を利用する事によりネットワーク障害に対する耐久性を向上することが出来る。通 常予想される様な、ネットワークケーブルの断線、ネットワークの機器の故障などが、万 が一発生しても、別の経路を利用して通信が継続されるため、実際のアプリケーションに 対する障害の影響を最小限とすることができる。ネットワークには、様々なハードウェア が使われている為に故障が起こる可能性を排除することはできない。今回検証したツール を有効活用することにより障害発生からの復旧を行うとともに、bonding 環境を構築するこ とで、アプリケーションへの影響を最小に抑えることは可能であると考える。今後の課題 として、bonding 環境で、ネットワークの経路変更にどれ位の時間がかかるか、計測を行う ことなどが挙げられる。 - 3-104 - 3.5 ディスク情報収集ツールの評価 ディスク情報収集の評価として、以下の機能評価を行なう事とする。 Storage Manager, df, raidtools, mdadm, LVM2 3.5.1 ツールの使用方法 H/W RAID の監視ツールとして、StorageManager の評価を、S/W RAID の機能検証と して、mdadm,raidtools,df の評価を、LVM の機能検証として、LVM2 の評価を行なう。 3.5.1.1 Storage Manager H/W RAID監視できるStorage Mangerは、Adaptec社製のHostRAID/SCSIデバイスを監 視するツールである(詳細は、3.5.2.3 を参照)。要求環境として、aacraidの、1.1.5 以上が 必要である。aacraidのバージョン確認は、modinfoコマンドで確認することが出来る。 3.5.1.2 df df は、ファイルシステムのディスク容量の使用状況を表示するコマンドである。パーテ ィションごとに、総容量、使用量、空容量、使用率、マウントポイントをブロック(512byte) 単位で表示することができる。df の実行例を以下に示す。以降、書式、オプション、実行 例の順で記す。 df [options] [file...] 図 3.5-1 df 書式 表 3.5-1 df で使用できるオプション POSIX オプション -k デフォルトの 512 バイト単位の代わりに 1024 バイト単位を用い る。 -P `Filesystem N-blocks Used Available Capacity Mounted on' とい うヘッダをつけて 6 列で出力する GNU オプション a, --all サ イズが 0 ブロックのファイルシステムやタイプが `ignore' また は`auto' のファイルシステムもリスト表示に含める -i, --inodes ブ ロック単位での使用容量のかわりに inode の使用状況をリスト 表示する -k, --kilobytes デフォルトのブロックサイズを無視し、 1024 バイトを 1 ブロック - 3-105 - としてサイズを表示する -l, --local ローカルファイルシステムのみをリスト表示する -m, --megabytes メガバイト (1,048,576 バイト) ブロック単位でサイズを表示する -t fstype, タイプが fstype のファイルシステムのみをリスト表示する --type=fstype タイプが fstype のファイルシステムを除外する。 -x fstype, --exclude-type=fstype それぞれのサイズについて、例えばメガバイトなら M といったサイ -H, --si ズ文字を付加する -T, --print-type 各ファイルシステムのタイプを表示する --block-size=SIZE 使用量データを得る前に sync を呼ばない --sync 使用量データを得る前に sync を呼ぶ。システムによっては新しい結 果を得ることができる # df Filesystem /dev/md0 1K-blocks 20635516 2942904 16644384 62193 11203 47779 19% /boot 20635516 32928 19554360 1% /home /dev/hda1 /dev/md1 Used Available Use% Mounted on 16% / 図 3.5-2 df 実行例 3.5.1.3 smartmontools smartmontools は、ハードディスクが持っている自己診断機能を利用してディスクを監 視するツールである。SMART から得られる情報を監視することによって、ハードディスク の故障を未然に防げる可能性もある。 smartctl – SMART よるディスク監視ができる。 smartctl [options] device 図 3.5-3 smartctrl 書式 表 3.5-2 smartctl オプション SHOW オプション -i, --info Prints the device model number, serial number, firmware version, and ATA Standard version/revision -a, --all information. Prints all SMART information about the disk, or TapeAlert information about the tape drive or changer. RUN-TIME オプション -q TYPE, --quietmode=TYPE Specifies that smartctl should run in one of the two quiet modes described here. - 3-106 - -d TYPE, --device=TYPE Specifies the type of the device. The valid arguments to this option are ata, scsi, and 3ware,N. -T TYPE, --tolerance=TYPE Specifies how tolerant smartctl should be of ATA and SMART command failures. -b TYPE, --badsum=TYPE Specifies the action smartctl should take if a checksum error is detected in the: (1) Device Identity Structure, (2) SMART Self-Test Log Structure, (3) SMART Attribute Value Structure, (4) SMART Attribute Threshold Structure, or (5) ATA Error Log Structure. -r TYPE, --report=TYPE Intended primarily to help smartmontools developers understand the behavior of smartmontools on non-conforming or poorly conforming hardware. コマンド -s VALUE, --smart=VALUE Enables or disables SMART on device. -o VALUE, --offlineauto=VALUE Enables or disables SMART automatic offline test, which scans the drive every four hours for disk defects. -S VALUE, --saveauto=VALUE Enables or disables SMART autosave of device vendor-specific Attributes. DISPLAY オプション -H, --health SMART status is based on information that it has gathered from online and offline tests, which were used to determine/update its SMART vendor-specific Attribute values. -c, --capabilities Prints only the generic SMART capabilities. -A, --attributes Prints only the vendor specific SMART Attributes. -l TYPE, --log=TYPE Prints either the SMART Error Log, the SMART Self-Test Log, the SMART Selective Self-Test Log [ATA only], or theLog Directory [ATA only]. -v N,OPTION, --vendorattribute=N,OPTION Sets a vendor-specific display OPTION for Attribute N. -F TYPE, --firmwarebug=TYPE Modifies the behavior of smartctl to compensate for some known and understood device firmware bug. -P TYPE, --presets=TYPE Specifies whether smartctl should use any preset options that are available for this drive. OFFLINE TEST AND SELF-TEST オプション -t TEST, --test=TEST Note that only one test type can be run at a time, so only one test type should be specified per command line. -C, --captive Runs self-tests in captive mode. 3.5.1.4 raidtools raidtools は、S/W RAID 構成向けのコマンドが用意されている。以下はコマンド一覧で - 3-107 - ある。実行例として、実行例として、raidhotadd の使い方を示す。raidhotadd は、障害発 生後、RAID 構成を戻すときに使用するコマンドである。 表 3.5-3 raidtools に含まれているコマンド一覧 detect_multipath – md デバイスを検出する。 detect_multipath [OPTION...] 図 3.5-4 detect_multipath 書式 表 3.5-4 detect_multipath オプション -v, --verbose Print out extra information -s, --superblock Print out only those devices that already have a valid multipath raid superblock -n, --new Print out only those devices that don't have a valid multipath superblock --usage Display brief usage message lsraid - md デバイスの状態確認を表示する。 lsraid -A [-g|-s|-f] {-a <device> | -d <device>} ... lsraid -A -p lsraid -D [-l] {-a <device> | -d <device>} ... lsraid -D -p lsraid -R {-a <device> | -d <device>} ... lsraid -R -p lsraid -h lsraid –V 図 3.5-5 lsraid 書式 表 3.5-5 lsraid オプション -A Selects array-based operation -a <device> Adds md device <device> to the list of devices to query. -D Selects disk-based operation. -d <device> Adds block device <device> to the list of devices to query. -f Displays only failed block devices in array-based mode (-A). -g Displays only good block devices in array-based mode (-A). -l Displays a long dump of block device superblocks in disk-based mode(-D). -p Scans all block devices in /proc/partitions for RAID arrays. -R Selects raidtab operation. -s Displays only spare block devices in array-based mode - 3-108 - (-A). mkraid – md デバイスを作成する。 mkraid [--configfile] [--version] [--force] [--upgrade] [-cvfu] </dev/md?>+ 図 3.5-6 mkraid 書式 表 3.5-6 mkraid オプション -c, --configfile filename Use filename as the configuration file (/etc/raidtab is used by default). -f, --force Initialize the consituent devices, even if they appear to have data on them already -o, --upgrade This option upgrades older arrays to the current kernel's RAID version, without destroying data. raid0run – raid0/LINEAR を起動させる。 raid0run [--configfile] [--version] [--force] [--upgrade] [-acvfuv] </dev/md?>+ 図 3.5-7 raid0run 書式 表 3.5-7 raid0run オプション -c, --configfile filename Use filename as the configuration file (/etc/raidtab is used by default). -a, --all Starts up all nonpersistent RAID0 and LINEAR arrays defined in raidtab. raidhotadd – md デバイスにディスクを追加する。 raidhotadd [--all] [--configfile] [--help] [--version] [-achv] </dev/md?>* 図 3.5-8 raidhotadd 書式 # raidhotadd /dev/md1 /dev/hdb2 図 3.5-9 raidhotadd 実行例 raidhotremove – md デバイスからディスクを外す。 raidhotremove [--all] [--configfile] [--help] [--version] [-achv] </dev/md?> 図 3.5-10 raidhotremove 書式 # raidhotremove /dev/md1 /dev/hdb2 図 3.5-11 raidhotremove 実行例 raidreconf – raid 構成を変更する。 - 3-109 - raidreconf -o oldraidtab -n newraidtab -m /dev/md? raidreconf -i /dev/sd? -n newraidtab -m /dev/md? raidreconf -n newraidtab -m /dev/md? -e /dev/sd?? 図 3.5-12 raidreconf 書式 表 3.5-8 raidreconf オプション -o {--old} oldraidtab Specifies the path name of the old (current) {--new} newraidtab Specifies the -m {--mddev} /dev/md? Specifies the name of the raid array to modify. -i {--import} /dev/sd?? Specifies the name of the device to import from. -e {--export} /dev/sd?? Specifies the name of the device to export to. raidtab. path name of the new raidtab. raidsetfaulty – md デバイスの無効にする。 raidsetfaulty [--all] [--configfile] [--help] [--version] [-achv] </dev/md?>* 図 3.5-13 raidsetfaulty 書式 raidstart/ raidstop – md デバイスの開始、停止をする。 raidstart [options] <raiddevice>* raidstop [options] <raiddevice>* 図 3.5-14 mdstart/mdstop 書式 3.5.1.5 mdadm mdadm は md デバイスの作成,管理,監視するためのプログラムである。 Linux の S/W RAID は md (Multiple Devices) デバイスドライバとして実装されている。 現状 Linux ではリニア md デバイス,RAID 0 (ストライピング),RAID 1 (ミラーリング), RAID 4,RAID 5,RAID 6 そしてマルチパス(MULTIPATH) がサポートされている。以 下に、S/W RAID を監視するツールをインストールする方法を示す。 rpm -ivh /var/src/rpm/RPMS/i586/mdadm-1.12.0-1.i586.rpm 図 3.5-15 mdadm インストール 表 3.5-9 mdadm 書式 Assemble モード mdadm --assemble <RAID Device> <Options, ArrayDevices>... mdadm --assemble --scan <RAID Device, Options>... mdadm --assemble --scan options... Build モード mdadm --build <RAID Device> --chunk=X --level=Y --RAID Devices=<Array - 3-110 - Devices> mdadm --create <RAID Device> --chunk=X --level=Y --RAID Devices=<Array Create モード devices> mdadm <RAID Device> <Options>... <Array Devices>.. Manage モード 表 3.5-10 mdadm で指定できるオプション モード Assemble 作成されたアレイの構成情報を元に 1 つのアクティブアレイを編成する Build デバイスごとのスーパブロックをもたない古いタイプのレガシーアレイを作成する。 Create デバイスごとのスーパブロックをもつアレイを作成する Manage スペアデバイスを追加することができ、欠陥のあるデバイスをアレイから外すなどの管 理を行う Misc 個々のデバイスに対して様々な操作を行う Follow md デバイスをモニタし、状態変化を検出して指定したアクションを起こさせる or Monitor オプション -A, --assemble 存在していたアレイを編成する。 -B, --build スーパブロックをもたないアレイ(レガシーアレイ)を作る -C, --create アレイの新規作成を行う -Q, --query md デバイスや md アレイの構成デバイスについての情報を表示する -D, --detail 1 つまたは複数の md デバイスの詳細な情報を表示する -E, --examine 1 つまたは複数のデバイスの md スーパブロックの内容を表示する -F, --follow, モニタモードを選択する --monitor -b, --brief 概要表示。 これは --detail や --examine と共に用いられる -c, --config= コンフィグファイルの指定。 デフォルトは /etc/mdadm.conf -s, --scan 不足情報を補うためにコンフィグファイルか /proc/mdstat をスキャンする Create/ Build モードのオプション -c, --chunk= 処理単位をキロバイトで指定する --rounding= リニアアレイにおける丸め係数を指定 -l, --level= RAID のレベルを指定する --create において指定できる値は次の通り。 linear, RAID0, 0, stripe, RAID1, 1, mirror, RAID4, 4, RAID5, 5, RAID6, 6, multipath, mp -p, --parity= RAID 5 のパリティ生成アルゴリズムを指定する。 指定できる値は次の通り left-asymmetric, left-symmetric, right-asymmetric, right-symmetric, la, ra, ls, rs デフォルトは left-symmetric - 3-111 - -n, --raid-devices= アレイ内のアクティブなデバイスの数 -x, アレイに対するスペアデバイスの数 --spare-devices= スペアは後から追加したり外したりできる -z, --size= RAID 1/4/5 における各ドライブの使用容量をキロバイトで指定 Assemble モード -u, --uuid= 編成するアレイの uuid を指定する -m, --super-minor= 作成されるアレイのマイナーデバイス番号を指定する -f, --force スーパブロックが古くてもアレイの作成を行う。 -R, --run アレイを構成するドライブの数が必要数に満たなくてもアレイを起動させる -U, --update= アレイ編成時、各デバイスのスーパブロックを更新する Manage モードのオプション -a, --add 指定されたデバイス(群)を、アレイを止めずに追加 -r, --remove 指定されたデバイス(群)を削除する -f, --fail 指定されたデバイス(群)に対し、不良であることを示すマークを付ける Misc モードのオプション: -R, --run 部分的に構成されたアレイを起動させる。 -S, --stop アレイを非アクティブにし、すべてのリソースを開放する -o, --readonly アレイに読取り専用マークを付ける。 -w, --readwrite アレイに読書き可マークを付ける。 --zero-superblock デバイスが有効な md スーパブロックをもつ場合、その内容をゼロで上書きする Monitor モードのオプション -p,--program, -alert イベントを検出した時に起動するプログラムを指定する -d, --delay md アレイの状態をポーリングする周期を秒で指定する デフォルトは 60 秒 -f, --daemonise mdadm がモニタ動作を行う場合、バックグラウンドデーモンとする -1, --oneshot アレイのチェックを 1 回だけ行う mdadm コマンドにて、RAID 構成を確認する。 # mdadm -Q --detail /dev/md0 /dev/md0: Version : 00.90.01 Creation Time : Tue Aug 30 15:25:24 2005 Raid Level : raid5 Array Size : 20964608 (19.99 GiB 21.47 GB) Device Size : 10482304 (10.00 GiB 10.73 GB) Raid Devices : 3 Total Devices : 2 Preferred Minor : 0 Persistence : Superblock is persistent - 3-112 - Update Time : Wed Sep 7 12:47:07 2005 State : clean, degraded Active Devices : 2 Working Devices : 2 Failed Devices : 0 Spare Devices : 0 Layout : left-asymmetric Chunk Size : 64K UUID : 863caab1:854a897f:3fc0053a:c5e50c4d Events : 0.57253 Number Major Minor RaidDevice State 0 3 2 0 active sync 1 0 0 - removed 2 22 65 2 active sync /dev/hda2 /dev/hdd1 図 3.5-16 mdadm 実行例 3.5.1.6 LVM2 LVM は、カーネル 2.4 からサポートされた強力なディスク管理機能であり、カーネル 2.6 では根本的な設計の見直しが行われ、LVM2(Logical Volume Manager Version2)へ とバージョンアップしている。LVM を利用すると物理的に複数のハードディスクをグルー プ化して 1 つの論理的なディスクに見せることができる。論理的なディスクには、SCSI、 IDE などのインターフェースに関係なく仮想的なディスクを作成することができる。 pvcreate – フィジカルボリュームの作成 pvcreate [-d|--debug] [-f[f]|--force [--force]] [-y|--yes] [-h|--help] [-t|--test] [--labelsector] [-M|--metadatatypetype] [--metadatacopies#copies] [--restorefilefile] [--setphysicalvolumesizesize] [--version] [PhysicalVolume...] 図 3.5-17 pvcreate 書式 表 3.5-11 pvcreate オプション オプション - 3-113 - [-v|--verbose] [--metadatasizesize] PhysicalVolume -f, --force Force the creation without any confirmation. -u, --uuid uuid Specify the uuid for the device. -y, --yes Answer yes to all questions. METADATA オプション --metadatasize The approximate amount of space to be set aside size for each meta data area. --metadatacopies The number of metadata areas to set aside on each copies PV. --restorefile file By default the PV is labelled with an LVM2 identifier --labelsector sector in its second sector (sector 1). Overrides the automatically-detected size of the PV. --setphysicalvolumesize size pvdisplay – フィジカルボリュームの表示 vdisplay [-c/--colon] [-d/--debug] [-h/-?/--help] [-s/--short] [-v[v]/--verbose [--verbose]] PhysicalVolumePath [PhysicalVolumePath...] 図 3.5-18 pvdisplay 書式 表 3.5-12 pvdisplay オプション -c, --colon Generate colon separated output for easier parsing in scripts or programs. -s, --short Only display the size of the given physical volumes. -m, --maps Display the mapping of physical extents to logical volumes and logical extents. vgcreate -ボリュームグループの作成 vgcreate [--addtag Tag] [-l|--maxlogicalvolumes [-A|--autobackup {y|n}] MaxLogicalVolumes] [-p|--maxphysicalvolumes MaxPhysicalVolumes] [-d|--debug] [-h|--help] [-M|--meta-datatypetype] [-s|--physicalextentsize PhysicalExtentSize[kKmMgGtT]] [-t|--test] [-v|--verbose] [--version] VolumeGroupName PhysicalVolumePath [PhysicalVolumePath...] 図 3.5-19 vgcreate 書式 表 3.5-13 vgcreate オプション -A, --autobackup {y|n} Controls automatic backup of VG metadata after the change. -l, --maxlogicalvolumes Sets the maximum possible logical volume count. MaxLogicalVolumes -p,--maxphysicalvolumes MaxPhysicalVolumes Sets the maximum possible physical volume count. -s,--physicalextentsize Sets the physical extent size on physical volumes of this volume - 3-114 - group. PhysicalExtentSize[kKmMgGtT] vgdisplay – ボリュームグループの表示 vgdisplay [-A|--activevolumegroups] [-c|--colon] [-d|--debug] [-h|--help] [--ignorelockingfailure] [-P|--partial] [-s|--short] [-v[v]|--verbose [--verbose]] [--version] [VolumeGroupName...] 図 3.5-20 vgdisplay 書式 表 3.5-14 vgdisplay オプション -A, --activevolumegroups Only select the active volume groups. -c, --colon Generate colon separated output for easier parsing in scripts or programs. Give a short listing showing the existence of volume groups. -s, --short lvcreate -ロジカルボリュームの作成 lvcreate [--addtag Tag] [-A/--autobackup y/n] [-C/--contiguous y/n] [-d/--debug] [-h/-?/--help] [-i/--stripes Stripes [-I/--stripesize StripeSize]] {-l/--extents LogicalExtentsNumber | -L/--size LogicalVolumeSize[kKmMgGtT]} [-M/--persistent y/n] [--minorminor] [-n/--name LogicalVolumeName] [-p/--permission r/rw] [-r/--readahead ReadAheadSectors] [-t/--test] [-v/--verbose] [-Z/--zero y/n] VolumeGroupName [PhysicalVolumePath...] lvcreate {-l/--extents LogicalExtentsNumber | -size LogicalVolumeSize[kKmMgGtT]} [-c/--chunksize ChunkSize] -s/--snapshot -n/--name SnapshotLogicalVolumeName OriginalLogicalVolumePath 図 3.5-21 lvcreate 書式 表 3.5-15 lvcreate オプション -c, --chunksize ChunkSize Power of 2 chunk size for the snapshot logical volume between 4k and 1024k. -C, --contiguous y/n Sets or resets the contiguous allocation policy for logical volumes. -i, --stripes Stripes Gives the number of stripes. This is equal to the number of physical volumes to scatter the logical volume. -I, --stripesize StripeSize Gives the number of kilobytes for the granularity of the stripes. -l, Gives the number of logical extents to allocate for the new --extents LogicalExtentsNumber logical volume. -L, Gives the size to allocate for the new logical - 3-115 - volume. --size LogicalVolumeSize[kKmMgGtT] --minor minor Set the minor number. -n, --name LogicalVolumeName The name for the new logical volume. -p, --permission r/w Set access permissions to read only or read and write. -r, --readahead ReadAheadSectors Set read ahead sector count of this logical volume to a value between 2 and 120. Create a snapshot logical volume for an -s, --snapshot existing, so called original logical volume. Controls zeroing of the first KB of data in the new logical -Z, --zero y/n volume. lvdisplay – ロジカルボリュームの表示 lvdisplay [-c/--colon] [-d/--debug] [-h/-?/--help] [--ignorelockingfailure] [--maps] [-P/--partial] [-v/--verbose] LogicalVolumePath [LogicalVolumePath...] 図 3.5-22 lvdisplay 書式 表 3.5-16 lvdisplay オプション -c, --colon Deprecated. To be replaced with a more-powerful reporting tool. -m, --maps Display the mapping of logical extents to physical volumes and physical extents. vgextend -ボリュームグループにフィジカルボリュームの追加 vgextend [-A/--autobackup y/n] [-d/--debug] [-h/-?/--help] [-t/--test] [-v/--verbose] VolumeGroupName PhysicalDevicePath [PhysicalDevicePath...] 図 3.5-23 vgxtend 書式 lvextend -ロジカルボリュームのサイズの拡大 lvextend [-A/--autobackup y/n] [-d/--debug] [-h/-?/--help] [-i/--stripes Stripes [-I/--stripesize StripeSize]] {-l/--extents [+]LogicalExtentsNumber [+]LogicalVolumeSize[kKmMgGtT]} [-t/--test] [-v/--verbose] | -L/--size LogicalVolumePath [PhysicalVolumePath...] 図 3.5-24 lvextend 書式 表 3.5-17 lvextend オプション -l, --extents [+]LogicalExtentsNumber Extend or set the logical volume size in units of logical extents. -L, Extend or set the logical volume size in units in units of - 3-116 - --size [+]LogicalVolumeSize[kKmMgGtT] megabytes. -i, --stripes Stripes Gives the number of stripes for the extension. -I, --stripesize StripeSize Gives the number of kilobytes for the granularity of the stripes. 3.5.2 H/W RAID 5/1 評価環境 H/W RAID 構成環境において、ディスク障害を発生させた時の OS の挙動を監視し、障 害状態から回復する手順を確認する。 3.5.2.1 ハードウェア構成 以下に H/W RAID5/1 の検証を行なった環境を示す。 表 3.5-18 H/W RAID5/1 検証環境 ハード CPU Athlon64 3500+ メモリ 1GB RIAD カード SCSI RAID2200S HDD UltraSCSI 320 36GB x 3 表 3.5-19 H/W RAID5/1 構成時のパーティション情報 パーティション(sda) / 10GB swap 1GB /home 10GB 今回の環境では、H/W RAID 5/1 のディスクアサインは、/dev/sda となる。 3.5.2.2 ソフトウェア構成 Kernel2.6 を採用している Turbolinux 10 Server を使用して評価を行なった。使用した ソフトウェア構成は以下の通り。 表 3.5-20 ソフトウェア構成 ディストリビューション Turbolinux 10 Server Kernel 2.6.8-5 StorageManager 2.10 Swatch 3.1.1-1 StorageManager、mdadm、は別途環インストールした為、以降に構築方法を示す。 swatch はネットワーク環境構築を参照。 3.5.2.3 Storage Manager のインストール/設定 Linux 版 Storage Manager は、OSS ツールではないが、RAID カードを購入すると添付 - 3-117 - CD に収められている。モジュールは、RPM パッケージで提供されているので、インスト ールは簡単にできる。添付 CD に収録されている Storage Manager をインストール、起動 までの手順を以下に記す。 CD に収録されているパッケージをインストールする。 #rpm –ivh StorMan-2.10.i386.rpm 図 3.5-25 Storage Manager のインストール Storage Manager には、監視デーモンが必要であり、常時、store_agent を起動しておく必 要がある。 # /etc/init.d/store_agent start もしくは、 #chkconfig store_agent on 図 3.5-26 監視デーモンの起動 Storage Manager は、日本語表示が出来ないため、監視ツールを立ち上げる前に、 “LANG=C”と設定する必要がある。 # export LANG=C # /usr/StoreMan/StoreMan.sh 図 3.5-27 Storage Manager の起動 正常時稼動状態 正常稼動中の Storage Manager のイメージ(Storage Manager 画面)を添付する。 - 3-118 - 図 3.5-28 Storage Manager 画面 Storage Manager の設定 障害発生時、mail にて通知する為の設定を行なう。この設定を行なうことにより障害発 生通知が行えるようになる。(これ以外の設定は、とくにする必要はない。) 1. 通知設定 Local system をクリックし、Actions から、Agent actions を選び Configure 選択する。 下図“通知設定”の画面が表示されたら、Email Notifications タブを選択する。 - 3-119 - 図 3.5-29 通知設定 2. Email Notifications の設定 同ウィンドより、Email Notificationsのタブを選択し、ツールバーにあるAdd email recipientボタンを押し、下図 “送信先情報登録”が表示される。初期設定時、SMTPサーバ 設定が表示される。表示されたら、SMTPサーバのアドレスと、返信先のメールアドレスを 入力する。入力例としてSMTPには、”192.168.0.1”,”gateway.hoge.net”などを入力する。 Reply to email address には、”[email protected]”, “[email protected]” など入力す る(任意により設定可能)。 入力例) localhost, 192.168.255.10 等と設定する 入力例) root, admin などを設定する 図 3.5-30 SMTP サーバ設定 - 3-120 - Recipient name には、任意の名前を入力し、Email address には、障害報告通知を出した いアドレスを入力し、add ボタンを押すことにより、障害発生時に発信されるメールの送信 先の設定が終了する。 任意の名称を入力する 入力例) root, admin 障害報告通知を送信したいユ ーザアカウントを入力する。 入力例) root, admin 図 3.5-31 送信先情報登録 Event type には、以下の 3 種類を選択することが出来る。 表 3.5-21Eventtype で選択できるオプション Error 障害のみ Error, Warning 障害、警告のみ Error, Warning, Information 障害、警告、情報 登録後、メールの送信テストを行なう。Actions をクリックし Send test message を選択す る。エラーが表示されなかったら、送信されているものとする。 3.5.2.4 H/W RAID 5/1 機能検証項目 H/W RAID 環境下において、I/F ケーブルを引き抜き、擬似的なディスク I/O 障害を発生 させ、OS の挙動を確認し、ディスクを入れ換えて、自動再構築されることを確認する。 3.5.2.5 H/W RAID 5/1 機能検証手順 稼動中にディスクの I/F ケーブルを抜き、擬似障害を発生させる。擬似障害発生時に Storage Manager から通知される内容を確認した後、ディスクを交換して、再構成される ことを確認する。その際、Storage Manager で表示される情報を変化も監視する。 3.5.2.6 H/W RAID 5/1 機能評価結果と考察 障害発生時には、ボードが持っている障害検知機能(アラーム音)により、障害が発生した 事がわかる。また、製品の添付 CD に収録されている Storage Manager の併用使用により メールによる障害報告を受けることができるため、常時監視を行わなくても障害発生時に - 3-121 - は、メールによる通知によって、障害発生を知ることができた。また、ディスクを交換す る事により自動で RAID の再構成が行なわれることも確認できた。H/W RAID は障害検知、 復旧までをインターフェースボードがサポートしている場合が多く、 後に述べる S/W RAID の様にシステム管理者がコマンド操作で、それらの操作を行う必要は少ない。 3.5.3 S/W RAID 5/1 ディスク評価環境 S/W RAID 構成環境において、ディスク障害を発生させた時の OS の挙動を監視し、障害 状態から回復する手順を確認する。 3.5.3.1 ハードウェア構成 以下に S/W RAID5/1 の検証を行なった環境を示す。 表 3.5-22 S/W RAID5/1 検証環境 ハード CPU Athlon64 3500+ メモリ 1GB HDD IDE 80GB x 3~2 表 3.5-23 S/W RAID5 構成時のパーティション情報 パーティション(had) パーティション(hdb) パーティション(hdc) /boot 64MB / 10GB /home 10GB swap 1GB / 10GB /home 10GB / 10GB /home 10GB 表 3.5-24 S/W RAID1 構成時のパーティション情報 パーティション(had) パーティション(hdb) / 10GB /home 10GB swap 1GB / 10GB /home 10GB S/W RAID 5/1 環境でのディスクアサインは、/dev/md0,/dev/md1 となる。 3.5.3.2 ソフトウェア構成 Kernel2.6 を採用している Turbolinux 10 Server を使用して評価を行なった。使用した - 3-122 - ソフトウェア構成を示す。 表 3.5-25 ソフトウェア構成 ディストリビューション Turbolinux 10 Server kernel 2.6.8-5 smartmontools 5.33-1 lvm2 2.00.20-6 raidtools 1.00.3-2 mdadm 1.12.0-1 df 5.2.1 swatch 3.1.1-1 swatch はネットワーク環境構築を参照。 3.5.3.3 smartmontools smartmontools をインストールする。 # rpm –ivh /var/src/rpm/RPMS/i586/smartmontools-5.33-1.i586.rpm 図 3.5-32 smartmontools のインストール smartmontools を起動する前に、設定ファイル(/etc/smartd.conf)にて、監視するデバイス の設定を行い、サービスを起動する。表 3.5-11 は、/dev/md0,md1.md2 を監視し、ヘルス チェックを root ユーザへ情報を送信する。という設定を行なっている。 /etc/smartd.conf 抜粋 # A very silent check. Only report SMART health status if it fails # But send an email in this case #/dev/hdc -H -m [email protected] /dev/md0 -H -m root /dev/md1 -H -m root /dev/md2 -H -m root 図 3.5-33 smartd.conf 設定例 smartd の起動することにより、監視を開始できる。 ・監視用デーモンの開始 # /etc/init.d/smartd start ・監視用デーモンの常時起動設定 # chkconfig smartd on 図 3.5-34 smartmontools の監視デーモン起動 - 3-123 - 3.5.3.4 S/W RAID 5/1 機能検証項目 S/W RAID 環境下において、I/F ケーブルを引き抜き、擬似的なディスク I/O 障害を発生 させて、OS の挙動を調べる事とする。また、故障を想定してディスクの交換後、raidtools を使用して、再構成される事を確認する。 3.5.3.5 S/W RAID 5/1 機能検証手順 稼動中にディスクの I/F ケーブルを抜き、擬似障害を発生させる。擬似障害発生後の swatch 監視から通知される内容と、OS の挙動を確かめる。 S/W RAID に関しては、システムを一旦停止し、ディスクを入換え、raidhotadd コマンド にて、再構成が行えることを確認する。 3.5.3.6 S/W RAID 5/1 機能評価結果と考察 H/W RAID に比べ、障害発生時に障害検出することはできないが、OSS ツールの組み合 わせ(swatch, smartmontools 等)により、障害検知を行うことは可能である。障害発生後は、 mdadm, raidhotadd コマンドを利用する事により、RAID 構成を復元することが出来る。 S/W RAID は、H/W RAID 程、コストをかけずに RAID 構成を組めるというメリットもあ るが、デメリットとして、障害発生後のディスク交換時に、システムを停止するが必要が ある。 3.5.4 LVM 機能評価環境 ディスク障害を発生させた時の OS の挙動を監視し、障害状態から回復する手順を確認す る。LVM 構成にディスク障害を発生させた時の OS の挙動を監視し、復旧手順の確立をす る。 3.5.4.1 ハードウェア構成 以下に LVM の検証を行なった環境を示す。 表 3.5-26 LVM 検証環境 ハード CPU Athlon64 3500+ メモリ 1GB HDD IDE 80GB x 2 表 3.5-27 LVM 構成時のパーティション情報 パ ー テ ィ シ ョ ン (hda) パーティション(hdb) / 10GB swap 1GB LVM 10GB - 3-124 - 3.5.4.2 ソフトウェア構成 Kernel2.6 を採用している Turbolinux 10 Server を使用して評価を行なった。使用した ソフトウェア構成を示す 表 3.5-28 ソフトウェア構成 ディストリビューション Turbolinux 10 Server kernel 2.6.8-5 LVM2 2.00 swatch 3.1.1-1 swatch はネットワーク環境構築を参照。 3.5.4.3 ロジカルボリュームの作成 ロジカルボリュームは、仮想ディスク上に作成されたパーティションを指す。ロジカル ボリュームは通常パーティションと同様にマウントして使用できる。作成手順は以下に示 す 。 モ ジ ュ ー ル の 読 み 込 み と デ バ イ ス 作 成 を 行 な う 。 LVM の 設 定 を 行 な う 場 合 、 Device-Mapper と dm-snapshot のモジュールを読み込む。正常に読込まれたかを、lsmod コマンドで確認する。 # modprobe dm-mod # modprobe dm-snapshot 図 3.5-35 Device-Mapper 読込みコマンド # lsmod Module Size dm_snapshot 14876 dm_mod 48252 Used by 0 4 dm_mirror,dm_snapshot 図 3.5-36 Device-Mapper 読込み結果 “Device-Mapper 読込み結果”内で下線が引かれている情報が表示されていれば、LVM に必 要なモジュールが正しく読み込みこめていると判断できる。確認の後、Device-Mapper が 使用するデバイスファイル(/dev/mapper/control)を作成する。Turbolinux 10 Server の場合、 devmap_mknod.sh を実行することによりデバイスファイルが作成される。 # /sbin/devmap_mknod.sh Creating /dev/mapper/control character device with major:10 minor:63. 図 3.5-37 Device-Mapper 作成スクリプト LVM で管理できるパーティション(Linux LVM)を作成する。LVM 用パーティションの作成 は通常(FDISK)の操作と同じである。LVM で管理できるパーティションへの変更は、ファ イルシステムタイプを、Linux LVM(8e)に変更することで利用できる。 - 3-125 - # fdisk /dev/hdb The number of cylinders for this disk is set to 119150. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Command (m for help): p Disk /dev/hdb: 61.4 GB, 61492838400 bytes 16 heads, 63 sectors/track, 119150 cylinders Units = cylinders of 1008 * 512 = 516096 bytes Device Boot Start End Blocks Id System /dev/hdb1 1 19842 10000336+ 83 Linux /dev/hdb2 19843 39684 10000368 83 Linux Command (m for help): t Partition number (1-4): 1 Hex code (type L to list codes): 8e Changed system type of partition 1 to 8e (Linux LVM) Command (m for help): t Partition number (1-4): 2 Hex code (type L to list codes): 8e Changed system type of partition 2 to 8e (Linux LVM) Command (m for help): p Disk /dev/hdb: 61.4 GB, 61492838400 bytes 16 heads, 63 sectors/track, 119150 cylinders Units = cylinders of 1008 * 512 = 516096 bytes Device Boot Start End Blocks Id System /dev/hdb1 1 19842 10000336+ 8e Linux LVM /dev/hdb2 19843 39684 10000368 8e Linux LVM Command (m for help): w 図 3.5-38 /dev/hda4 を Linux LVM に設定 - 3-126 - 次にフィジカルボリュームの作成を行なう。pvcreate コマンドにて、LVM で使用可能な物 理パーティションを作成することができる。確認方法は、pvdisplay コマンドにて情報の確 認可能である。 # pvcreate /dev/hdb1 Physical volume "/dev/hdb1" successfully created 図 3.5-39 pvcreate によるフィジカルボリュームの作成 作成結果を、pvdisplay で確認する。 # pvdisplay --- NEW Physical volume --PV Name /dev/hdb1 VG Name PV Size 9.54 GB Allocatable NO PE Size (KByte) 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID IAnMKc-BJFE-q7Rt-13iq-cnwv-fkVW-6HwmAP 図 3.5-40 フィジカルボリュームの確認 フィジカルボリューム作成後に、仮想ディスクとなるボリュームグループを作成可能とな る。作成には、vgcreate コマンドで作成することができる。作成結果は、vgdisplay コマン ドで確認することができる。 # vgcreate vg_01 /dev/hdb1 Volume group "vg_01" successfully created 図 3.5-41 ボリュームグループの作成 作成結果を、vgdisplay で確認する。 # vgdisplay --- Volume group --VG Name vg_01 System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 - 3-127 - Cur LV 0 Open LV 0 Max PV 0 Cur PV 1 Act PV 1 VG Size 9.54 GB PE Size 4.00 MB Total PE 2441 Alloc PE / Size 0 / 0 Free 2441 / 9.54 GB PE / Size VG UUID zIUKkt-iX2e-iu5C-MY6m-szUX-axi9-7XhHAt 図 3.5-42 ボリュームグループの確認 作成したボリュームグループ上にロジカルボリュームを作成する。作成後、lvdisplay にて 構成確認を行なう。 # lvcreate -L 4G -n lv01 vg_01 Logical volume "lv_01" created 図 3.5-43 ロジカルボリュームの作成 # lvdisplay --- Logical volume --LV Name /dev/vg_01/lv01 VG Name vg_01 LV UUID b06gne-048G-ysTU-XoTS-glVI-mbiK-oOc3Uc LV Write Access read/write LV Status available # open 0 LV Size 4.00 GB Current LE 1024 Segments 1 Allocation inherit Read ahead sectors 0 Block device 253:3 図 3.5-44 lvdisplay 作成したロジカルボリューム上にファイルシステムを作成する。ファイルシステムの作成 には、mkfs コマンドを使用する。ファイルシステム作成後、mount コマンドにてマウント し、df コマンドでマウントされている確認を行なうことを勧める。 # mkfs.ext3 /dev/vg_01/lv01 - 3-128 - mke2fs 1.35 (28-Feb-2004) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) 524288 inodes, 1048576 blocks 52428 blocks (5.00%) reserved for the super user First data block=0 32 block groups 32768 blocks per group, 32768 fragments per group 16384 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736 Writing inode tables: done Creating journal (8192 blocks): done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 27 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override. 図 3.5-45 ロジカルボリュームの初期化 # mount /dev/vg_01/lv01 /mnt/lvm/ # df Filesystem 1K-blocks /dev/hda1 10317828 Used Available Use% Mounted on 5174084 4619628 32828 3885908 53% / /dev/mapper/vg_01-lv01 4128448 1% /mnt/lvm 図 3.5-46 ロジカルボリュームのマウント 3.5.4.4 スナップショットの作成 スナップショットを作成する事により、選択した LVM 領域のコピーを作成する事ができ る。 # lvcreate -s -L 4G -n snap01 /dev/vg_01/lv01 Logical volume "snap01" created 図 3.5-47 スナップショット作成 - 3-129 - 結果は lvdisplay にて確認することができる。 # lvdisplay --- Logical volume --LV Name /dev/vg_01/snap01 VG Name vg_01 LV UUID b06gne-048G-ysTU-XoTS-glVI-mbiK-oOc3Uc LV Write Access read/write LV snapshot status active destination for /dev/vg_01/lv01 LV Status available # open 0 LV Size 4.00 GB Current LE 1024 Segments 1 Snapshot chunk size 8.00 KB Allocated to snapshot 0.00% Allocation inherit Read ahead sectors 0 Block device 253:3 図 3.5-48 ロジカルボリュームの構成確認 3.5.4.5 構成変更 LVM はディスクの増設による領域拡張に柔軟に対応する事ができる。追加ディスクを LVM として定義し、pvcreate にてフィジカルボリュームとする。作業を行なう場合、 umount する必要がある。 # pvcreate /dev/hdc1 Physical volume "/dev/hdc1" successfully created 図 3.5-49 新規フィジカルボリュームの作成 追加分のフィジカルボリュームを既存のボリュームグループに追加する。これは、vgextend コマンドにて追加することができる。 # vgextend vg_01 /dev/hdc1 Volume group "vg_01" successfully extended 図 3.5-50 既存ボリュームグループに新規フィジカルボリュームを追加 ボリュームサイズが増えたことを vgdisplay コマンドにて確認する。下線が引かれている VG Size に違いがある事を確認する。 - 3-130 - 表 3.5-29 ボリュームグループの状況 # vgdisplay # vgdisplay --- Volume group --VG Name --- Volume group --vg_01 VG Name System ID vg_01 System ID Format lvm2 Format lvm2 Metadata Areas 1 Metadata Areas 2 Metadata Sequence No 4 Metadata Sequence No 5 VG Access read/write VG Access read/write VG Status resizable VG Status resizable MAX LV 0 MAX LV 0 Cur LV 2 Cur LV 2 Open LV 0 Open LV 0 Max PV 0 Max PV 0 Cur PV 1 Cur PV 2 Act PV 1 Act PV 2 VG Size 9.54 GB VG Size 12.55 GB PE Size 4.00 MB PE Size 4.00 MB Total PE 2443 Total PE 3212 Alloc PE / Size 2048 / 8.00 GB Alloc PE / Size 2048 / 8.00 GB Free 395 / 1.54 GB Free 1164 / 4.55 GB PE / Size PE / Size 既存ロジカルボリュームのサイズを変更する。 # lvextend -L 11G /dev/vg_01/lv01 Extending logical volume lv01 to 11.00 GB Logical volume lv01 successfully resized 図 3.5-51 ロジカルボリュームのサイズ変更 アンマウントし、フォーマットを行なう。 # umount /mnt/lvm/ # mkfs.ext3 /dev/vg_01/lv01 mke2fs 1.35 (28-Feb-2004) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) 1441792 inodes, 2883584 blocks 144179 blocks (5.00%) reserved for the super user - 3-131 - First data block=0 88 block groups 32768 blocks per group, 32768 fragments per group 16384 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208 Writing inode tables: done Creating journal (8192 blocks): done Writing superblocks and filesystem accounting information:done 図 3.5-52 構成変更後のフォーマット 再度、マウントし容量が増えた事を確認する。 # mount /dev/vg_01/lv01 /mnt/lvm # df Filesystem 1K-ブロック 使用 使用可 使用% マウント位置 /dev/hda1 10317828 2932188 6861524 /dev/hda3 9851340 32916 9318000 30% / 1% /home /dev/mapper/vg_01-lv01 11353328 32828 10743784 1% /mnt/lvm* 図 3.5-53 構成変更後確認 */mnt/lvm は任意で作成したマウントポイントである。 3.5.4.6 LVM 機能検証項目 LVM 環境下において、I/F ケーブルを引き抜き、擬似的なディスク I/O を行えない状況 下において OS の挙動を調べる事とする。その際、復旧する手順についても検証する。 3.5.4.7 LVM 機能検証手順 稼動中にディスクの I/F ケーブルを抜き、擬似障害を発生させる。擬似障害発生後の swatch 監視から通知される内容と、OS の挙動を確かめる。環境復旧時に何が問題となる のか要因を調べ、対処法を確立する。 3.5.4.8 LVM 機能評価結果と考察 LVM 構成下において障害が発生した場合、RAID のようなミラーリング機能は備わって いない為、記録されている情報の保守が必要になるが、LVM に実装されているスナップシ - 3-132 - ョット等の機能を使いこなすことにより、万が一の状況を未然に防ぐことができる。実際、 スナップショットを利用したバックアップを利用した大型 non-stop システムを運用してい る実例もある。通常使用される ext3,ext2 のファイルシステムに比べ、環境構築に費やす時 間は多いが、運用開始以後のメンテナンス性、拡張性には優れたものがある為に使いやす い機能であると思われる。 - 3-133 - 3.6 ダンプツールの評価 3.6.1 ダンプ採取ツール diskdump、netdump、LKCD、kdump、mkdumpのダンプ採取ツールの紹介を行った 後、3.6.1.6 でダンプ採取ツールの比較を行い、3.6.1.7 でダンプ採取ツールの考察を行う。 3.6.1.1 diskdump ■ 概要 diskdump は富士通社が開発したダンプ採取方法であり、障害時にクラッシュダンプを ディスク上に採取する仕組みである。この機能を使用するためには、カーネルに含まれ る SCSI ドライバに修正が必要となるが、 Red Hat linux のディストリビューションは 標準で diskdump 機能が組み込まれており、カーネル再生成を行うことなく使用するこ とができる。 採取されたダンプファイルは、crash、lcrash、Alicia ユーティリティで解析可能である。 尚、crash を使用する場合は、デバッグオプション付のカーネルを作成する必要がある。 http://sourceforge.net/projects/lkdump/ ■ インストール環境 kernel 2.6.9-11.EL カーネル マシン アーキテクチャー i386 OS DELL PowerEdge 2600 Red Hat Enterprise Linux AS 4 update1 メモリ 2GB ■ 対応ダンプ編集ツール crash、lcrash、Alicia ■ 導入手順 (1) インストールされている diskdump の確認 # rpm -qa |grep diskdump diskdumputils-1.0.1-5 (2) ディスクの準備 diskdump の採取先として使用できるのは、以下のドライバを使用するディスクで ある。 aic7xxx、aic79xx、mpt fusion、megaraid、ata_piix、sata_promise (3) ダンプパーティションの作成 - 3-134 - ダンプの採取先として用意したディスク上に、搭載メモリの 1.5 倍程度のダンプパ ーティションを作成する。ここでは/dev/sdb1 を diskdump 用のパーティションと する。 (4) ダンプデバイスの設定 /etc/sysconfig/diskdump を修正し、ダンプデバイス名を記述する。 DEVICE=/dev/sdb1 (5) ダンプデバイスの初期化 /etc/sysconfig/diskdump に登録したパーティションを dump disk 形式にフォーマ ットするために、以下のコマンドを実行する。 # service diskdump initialformat (6) diskdump サービスの開始 以下のコマンドを実行する。これにより、diskdump サービスがシステム起動時に 起動されるようになる。 # chkconfig diskdump on 以下のコマンドを実行し、diskdump サービスを起動する。 # service diskdump start ファイル/proc/diskdump が作られ、ダンプデバイスの情報が記述されていれば、起 動は正常に完了している。 # cat /proc/diskdump /dev/sdb1 63 39086082 ■ 動作確認 (1) SysRq マジックキーの有効化 # echo 1 > /proc/sys/kernel/sysrq (2) ダンプの採取 # echo c > /proc/sysrq-trigger ダンプ採取後、halt される。 (3) ダンプファイルの確認 ダ ン プ は 、 サ ー バ 側 に /var/crash/ ク ラ イ ア ン ト I P ア ド レ ス - 採 取 日 時 ( 例 :/var/crash/192.168.0.2-2005-09-09-21:59) フ ォ ル ダ が 作 成 さ れ そ の 中 に vmcore ファイルとして保存される。 - 3-135 - 3.6.1.2 netdump ■ 概要 netdump は Red Hat 社が提供するクラッシュダンプをネットワーク経由で採取する為 の仕組みである。Red Hat Linux および、MIRACLE LINUX(V3.0SP1 以降)では標 準で対応されている。ダンプを取得するクライアントとダンプデータをネットワーク経 由で受け取って保存するサーバで構成され、クライアント/サーバ形式をとる。 採取されたダンプファイルは、crash、lcrash、Alicia ユーティリティで解析可能である。 尚、crash を使用する場合は、デバッグオプション付のカーネルを作成する必要がある。 ■ インストール環境 <クライアント> kernel 2.6.9-11.ELsmp カーネル マシン アーキテクチャー i386 OS DELL PowerEdge 2600 Red Hat Enterprise Linux AS 4 update1 メモリ 2GB <サーバ> カーネル kernel 2.6.9-11.EL マシン アーキテクチャー i386 OS DELL OptiPlex GX270 Red Hat Enterprise Linux AS 4 update1 メモリ 512MB ■ 対応ダンプ編集ツール crash、lcrash、Alicia ■ 導入手順(サーバ) (1) インストールパッケージの確認 netdump を行うサーバとクライアント間では ssh による認証を行う。また、 netdump-server は ssh-server と依存関係を持つ為、事前に ssh が導入されている 必要がある。 # rpm -qa |grep ssh-server openssh-server-3.9p1-8.RHEL4.4 # rpm -qa |grep netdump-server netdump-server-0.7.7-3 パッケージが導入されていない場合には、CD 等よりパッケージの導入を行う。 (2) パスワード設定 netdump-server の導入を行うと自動的に作成される netdump ユーザのパスワード 設定を行う。このパスワードはクライアントの認証を行う際に必要となる。 - 3-136 - # passwd netdump Changing password for user netdump. New UNIX password: Retype new UNIX password: passwd: all authentication tokens updated successfully. (3) サービスの起動確認 ssh および netdump-server のサービスを手動にて起動し正常に起動できているか ログを確認する。 # service sshd start Starting sshd: [ OK ] # service netdump-server start Starting netdump-server [ OK ] # tail /var/log/messages (途中 略) Sep 9 21:10:38 rhas4u1ipa sshd: succeeded Sep 9 21:10:45 rhas4u1ipa netdump-server: netdump-server startup succeeded (4) サービス自動起動の設定 手動によりサービスの起動が確認できたら、再起動後にサービスが自動起動するよう設 定する。 # chkconfig sshd on # chkconfig netdump on # chkconfig –list sshd sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off # chkconfig –list netdump-server netdump-server 0:off 1:off 2:on 3:on 4:on 5:on 6:off ■ 導入手順(クライアント) (1) インストールされているパッケージの確認 # rpm -qa |grep netdump netdump-0.7.7-3 パッケージが導入されていない場合には、CD 等よりパッケージの導入を行う。 (2) 設定ファイルの編集 /etc/sysconfig/netdump を修正しダンプの送信に使用する NIC および送信先(サー バ)の IP アドレスを設定する。 DEV=eth0 - 3-137 - NETDUMPADDR=192.168.0.4 NETDUMPADDR には IP アドレスを指定する。ネームサーバ等による名前解決は 利用できない為サーバのホスト名を指定することはできない。 (3) DSA 公開鍵の設定 netdump-server に DSA 公開鍵を登録する。以下の操作を行う前にクライアントと サーバをネットワーク接続し、サーバ側で netdump-server の設定およびサービス の起動を行っておく必要がある。 # service netdump propagate [email protected]’s password:XXXXXXXXXXXXX nn.nn.nn.nn にはサーバの IP アドレスが表示される。 XXXXXXXXXX にサーバで設定した netdump ユーザのパスワードを入力する。 (4) サービスの起動 netdump のサービスを手動にて起動し正常に起動できているかログを確認する。 # service netdump start initializing netdump [ OK ] initializing netconsole local IP nn.nn.nn.nn [ OK ] # tail /var/log/messages (途中 略) Sep 9 21:28:57 rhas4u1ipa netdump: initializing netdump succeeded Sep 9 21:28:57 rhas4u1ipa netdump: initializing netconsole succeeded Sep 9 21:28:57 rhas4u1ipa kernel: netconsole: network logging started (5) サービス自動起動の設定 手動によりサービスの起動が確認できたら、再起動後にサービスが自動起動するよう設 定する。 # chkconfig netdump on # chkconfig –list netdump netdump 0:off 1:off 2:on 3:on 4:on 5:on 6:off ■ 動作確認 (1) SysRq マジックキーの有効化 # echo 1 > /proc/sys/kernel/sysrq (2) ダンプの採取 # echo c > /proc/sysrq-trigger ダンプはネットワーク経由でサーバに転送される。ダンプ採取が終了するとクライ アントは自動的にリブートされる。 - 3-138 - (3) ダンプファイルの確認 ダ ン プ は 、 サ ー バ 側 に /var/crash/ ク ラ イ ア ン ト I P ア ド レ ス - 採 取 日 時 (例:/var/crash/192.168.0.2-2005-09-09-21:59)フォルダが作成されその中に vmcore ファイルとして保存される。 - 3-139 - 3.6.1.3 LKCD ■ 概要 LKCD(Linux Kernel Crash Dump)は、メモリダンプ採取機能およびメモリダンプ 解析ツール(lcrash ユーティリティ)の提供を目的とし、米国 SGI 社で開発され GPL ライセンスで公開された。その後、IBM 社、NEC 社、日立社、富士通社共同で拡張が 行われている。 MIRACLE LINUX V3.0 をインストールした場合、最小構成でも LKCD がインストー ルされる。 http://lkcd.sourceforge.net/ ■ インストール環境 カーネル kernel 2.4.21-20.19AXsmp マシン アーキテクチャー i386 OS DELL PowerEdge 2600 MIRACLE LINUX V3.0 2GB メモリ ■ 対応ダンプ編集ツール crash、lcrash、Alicia ■ 導入手順 (1) インストールされている LKCD の確認 # rpm -qa | grep lkcd lkcdutils-4.2-10AX lkcdutils-devel-4.2-10AX (2) ダンプパーティションの作成 ダンプの採取先として用意したディスク上に、搭載メモリの 1.5 倍程度のダンプパ ーティションを作成する。 領域確保後、/dev/vmdump にシンボリックリンクを張る。ここでは、/dev/sdb1 を ダンプ用のパーティションとする。デフォルトのスワップ・パーティションをダン プの吐き出し口にすることにより、システムのブートが早くなる。 # ln -s /dev/sdb1 /dev/vmdump (3) LKCD の設定 /etc/sysconfig/dump を修正し LKCD の設定を行う。 DUMP_ACTIVE=1 DUMPDEV=/dev/vmdump DUMPDIR=/var/log/dump - 3-140 - DUMP_SAVE=1 DUMP_LEVEL=8 DUMP_FLAGS=0x80000000 # disruptive disk dump is default for 2.4 DUMP_COMPRESS=2 PANIC_TIMEOUT=5 ・ DUMP_ACTIVE ⇒ LKCD が稼動中かを示すパラメータ。デフォルトは”1”。 “1” ---- LKCD は稼動中 “0” ---- LKCD は非稼動 ・ DUMPDEV ⇒ メモリ内容を保存するデバイスを示すパラメータ。デフォルトは /dev/vmdump/dev/vmdump はシンボリックリンクとなっており、デフォルトでは スワップ・デバイスがリンク先となっている。 ・ DUMPDIR ⇒ ダンプ保存先ディレクトリを示すパラメータ。デフォルトは/var/log/dump。 ・ DUMP_SAVE ⇒ ダンプ採取と crash レポート(ダンプのサマリ表示)の設定を示すパラメー タ。デフォルトでは”1”。 “1” ---- ダンプ採取と crash レポート作成を行う。 “1” 以外 ---- crash レポート作成のみを行う。 ・ DUMP_LEVEL ⇒ ダンプ採取領域を示すパラメータ。デフォルトは”8”。 “0” (DUMP_NONE) ---- ダンプ採取は行わない。 “1” (DUMP_HEADER) ---- 先頭 128byte のダンプヘッダを採取。 “2” (DUMP_KERN) ---- ダンプヘッダ+使用カーネルページを採取。 “4” (DUMP_USER) ---- ダンプヘッダ+使用カーネルページ+ ユーザページを採取。 “8” (DUMP_ALL) ---- 全て(未使用カーネルページも含め)採取。 ・ DUMP_FLAGS ⇒ ダンプ採取後のリブートアクションを示すパラメータ。デフォルトは”0”。 “0” (DUMP_FLAG_NONE) ---- “1” (DUMP_FLAGS_NONDISRUPT) ---- - 3-141 - リブートを行う。 リブートを行わない。 ・ DUMP_COMPRESS ⇒ ダンプの圧縮機能を示すパラメータ。デフォルトは”2”。 “0” (DUMP_COMPRESS_NONE) ---- 圧縮を行わない。 “1” (DUMP_COMPRESS_RLE) ---- RLE 圧縮を行う。 “2” (DUMP_COMPRESS_GZIP) ---- GZIP 圧縮を行う。 ・ PANIC_TIMEOUT ⇒ ダンプ採取終了後のカーネルのアクションを示すパラメータ。デフォルト は”5”。 “0” “0” 以外 ---- カーネルはスピンループのまま。(リブートを行わない) ---- ダンプ採取後、指定された秒数待ってからリブートを行う。 (4) LKCD 設定ファイルの反映 設定ファイルを反映させるために、以下のコマンドを実行する。 # lkcd config (5) ダンプ保存ディレクトリの内容 LKCD の設定パラメータである DUMPDIR で示されたダンプ保存ディレクトリは、 ・ ダンプファイルディレクトリ(DUMPDIR/xxx ⇒ xxx は数字で表される) ・ bounds ファイル で構成される。bounds ファイルには、次にダンプファイルを保存する際に使用する 数字が含まれている。例えば、bounds ファイルの内容が『1』で、カーネルパニッ クが発生した場合、ダンプ採取後は/var/log/dump/1 ディレクトリ内にダンプファイ ルが保存される。このとき bounds ファイルの内容は『2』となっている。 次にダンプファイルディレクトリに保存される内容を示す。”n”は作成されたディレ クトリ(=数字)を表している。 ・ dump.n ⇒ crash ダンプファイル(LKCD 形式) ・ kerntypes.n ⇒ Linux カーネルのデータ構造が含まれているファイル。(Binary 形式) Kerntypes ファイルは通常 Linux カーネルをコンパイルしたときに作成され、/boot ディレクトリに Kerntypes-2.4.21-20.19AXsmp として保存される。 kerntypes.n ファイルはこの Kerntypes-2.4.21-20.19AXsmp ファイルのコピーと なっている。 (例) /boot/Kerntypes-2.4.21-20.19AXsmp -> Kerntypes.n - 3-142 - ・ map.n ⇒ Linux カーネルのシンボルテーブル(外部参照)が含まれているファイル。 (Text 形式) map ファイルは通常、Linux Kernel をコンパイルしたときに作成され、/boot ディ レクトリに System.map-2.4.21-20.19AXsmp として保存される。map.n ファイル はこのファイルのコピーとなっている。 (例) /boot/System.map-2.4.21-20.19AXsmp -> map.n ・ analysis.n ⇒ 自動的に作成される Crash レポートファイル。(Text 形式) ・ lcrash.n ⇒ /sbin にある lcrash ユーティリティのコピー。(Binary 形式) ■ 動作確認 (1) SysRq マジックキーの有効化 # echo 1 > /proc/sys/kernel/sysrq (2) ダンプの採取 # echo c > /proc/sysrq-trigger ダンプ採取後、PANIC_TIMEOUT パラメータ値が 0 以外の場合、リブートされる。 (3) ダンプファイルの確認 /var/log/dump ディレクトリ以下に保存されたファイルを確認する。 - 3-143 - 3.6.1.4 kdump ■ 概要 kexec は、システム再起動時に時間がかかるファームウェアやブートローダの手順を介 さずに、高速にリブートさせ、別のカーネルを起動させることができる。この kexec の 機能を使用して、障害が発生した時に、ダンプ採取用カーネルを起動させ、障害が発生 したメモリ空間にアクセスすることを可能にしたのが kdump である。 以下の手順では、障害が発生し、ダンプを採取される側のカーネルをファーストカー ネル、ダンプを採取する側のカーネルをセカンドカーネルとして説明している。セカ ンドカーネルは、ファーストカーネル起動後、kexec コマンドによりメモリ空間にロー ドされる。ファーストカーネル クラッシュ時に、セカンドカーネルが起動される。 http://lse.sourceforge.net/kdump/ ■ インストール環境 カーネル kernel 2.6.13 マシン アーキテクチャー i386 OS DELL PowerEdge 2600 Red Hat Enterprise Linux AS 4 update1 メモリ 2GB ■ 対応ダンプ編集ツール gdb ■ 導入手順 (1) ファイルのコピー 次のファイルをダウンロードし、任意のディレクトリにコピーする。 ・ kexec-tool のソース kexec-tools-1.101.tar.gz ・ kdump 用パッチ kexec-tools-1.101-kdump.patch ・ カーネルソース linux-2.6.13.tar.bz2 (2) kexec-tool に kdump のパッチを適用しインストール # tar zxvf kexec-tools-1.101.tar.gz # patch -p0 < kexec-tools-1.101-kdump.patch # cd <kexec-toolを導入したディレクトリ> # ./configure # make # make install (3) Kernel 2.6.13 を展開 # tar jxvf linux-2.6.13.tar.bz2 - 3-144 - (4) ファーストカーネルの生成 # make menuconfig Processor type and features ---> [*] kexec system call (EXPERIMENTAL) (0x100000) Physical address where the kernel is loaded File systems ---> Pseudo filesystems ---> [*] sysfs file system support # make # make modules_install # make install /boot/grub/menu.lst を修正し crashkernel パラメータを追加する。 title Red Hat Enterprise Linux AS (2.6.13) root (hd0,0) kernel /vmlinuz-2.6.13 ro root=LABEL=/ rhgb quiet crashkernel=64M@16M initrd /initrd-2.6.13.img ここで、crashkernel パラメータの 64M はセカンドカーネル用に確保するメモリ容 量であり、16M は確保するメモリ領域の最初のアドレスである。 設定完了後リブートしファーストカーネルを起動する。 # reboot 起動後、カーネルが 2.6.13 であることを確認する。 # uname –r 2.6.13 (5) セカンドカーネルの生成 # make menuconfig Processor type and features ---> [ ] Symmetric multi-processing support [*] Local APIC support on uniprocessors [*] IO-APIC support on uniprocessors [*] kernel crash dumps (EXPERIMENTAL) (0x1000000) Physical address where the kernel is loaded File systems ---> Pseudo filesystems [*] セカンドカーネル起動時に ---> /proc/vmcore support (EXPERIMENTAL) [*] /dev file system support (OBSOLETE) - 3-145 - “Warning: unable to open an initial console.” が出力される 場合の対応 Device Drivers ---> SCSI device support ---> 今回は MPT SCSI デバイス <*> SCSI device support <*> を使用している為この設定 SCSI disk support Fusion MPT device support ---> を行っている。 <*> Fusion MPT (base + ScsiHost) drivers # make # make vmlinux 注意:kexec –p で使用されるセカンドカーネルには、vmlinux image を使用する。 bzImage は使用できない。 (6) kexec の実行 ファーストカーネルがカーネルパニックになった時に起動されるダンプ採取用セ カンドカーネルを kexec コマンドでロードする。 # kexec -p ./vmlinux-2.6.13-2nd --crashdump --args-linux --append="root=/dev/sdb1 init 1 irqpool" ここで指定している vmlinux-2.6.13-2nd は、(5)で作成したセカンドカーネルの vmlinux image である。 (7) /dev/console の追加 セカンドカーネル起動時に"Warning: unable to open an initial console"と出力さ れ、画面が表示されない場合の対応として、/dev/console を静的に作成する。 # mkdir test # mount --bind / test # cd test/dev # mknod -m 660 console c 5 1 # cd ../.. # umount test # rmdir test ■ 動作確認 (1) カーネルパニックによるセカンドカーネルへの切替え ファーストカーネルのパニックにより、ダンプ採取のためのセカンドカーネルが起 動される。 テストのため、次の入力によりカーネルパニックを発生させる。 # echo 1 >/proc/sys/kernel/sysrq # echo c >/proc/sysrq-trigger (2) ダンプファイルへの書き込み - 3-146 - 起動されたセカンドカーネルからは、二つのフォーマットで、クラッシュしたメモ リ空間にアクセスすることが出来る。 ・elf format ・raw format # cp /proc/vmcore /proc/vmcore /dev/oldmem <dump-file> コピーしたダンプファイルは、-g オプションで生成した vmlinux を使用して gdb で解析することができる。また、このダンプファイルは、crash には対応されてい ない。 linux-2.6.13/Documentation/kdump/に 、 gdb マ ク ロ gdbmacros.txt が あ り 、 bttnobp,btt,btpid,trapinfo などが追加されている。 [実行例] # gdb ./vmlinux ./vmcore --command=gdbmacros.txt #0 0xc011543c in crash_get_current_regs (regs=0xf6e81ef4) at arch/i386/kernel/crash.c:102 102 regs->eip = (unsigned long)current_text_addr(); (gdb) bttnobp pid 1; comm init: =================== __alloc_pages + 617 in section .text schedule_timeout + 82 in section .text process_timeout in section .text do_select + 880 in section .text copy_to_user + 98 in section .text cp_new_stat64 + 234 in section .text __pollwait in section .text sys_select + 744 in section .text sysenter_past_esp + 84 in section .text - 3-147 - 3.6.1.5 mkdump ■ 概要 mkdump(Mini Kernel Dump)はNTTデータ社、VA Linux社により開発され、kdump と同じように障害が発生したカーネルとは別のダンプ採取用カーネル(ミニカーネル) を使用してダンプ採取する機能である。ミニカーネルは、kexecなどをもとに開発され ているが、kexecに対して次のような優位性がある。 ・ ダンプイメージがミニカーネルにより、ディスクに書き出される。 ・ ダンプフォーマット変換ツールにより、lcrashで解析が可能。 ・ kexecは、セカンドカーネル起動時に、ファーストカーネルに上書きして稼動して しまう。 障害が発生してダンプ採取される側にmkexecをロードし、パニック発生時にダンプ採 取用のミニカーネルを起動する。 http://mkdump.sourceforge.net/ ■ インストール環境 カーネル kernel 2.6.9 マシン アーキテクチャー i386 OS DELL PowerEdge 2600 Red Hat Enterprise Linux AS 4 update1 メモリ 2GB ■ 対応ダンプ編集ツール crash、lcrash、Alicia ■ 導入手順 (1) ファイルのコピー 次のファイルをダウンロードし、任意のディレクトリにコピーする。 ・ミニカーネルのパッチ minik-2.6.9.-1.0.patch ・カーネルソース linux-2.6.9.tar.bz2 ・mkexec のソース mkexec-2.6.9-1.0.taz (2) ミニカーネルのパッチ適用 # tar jxvf linux-2.6.9.tar.bz2 # mv linux-2.6.9 linux-2.6.9-minik # cp minik-2.6.9-1.0.patch linux-2.6.9-minik # cd linux-2.6.9-minik # patch -p1 < minik-2.6.9-1.0.patch (3) ミニカーネルの作成 - 3-148 - # make menuconfig General setup ---> [*] Make dump mini kernel [ ] --- Run the mini kernel on PAE mode (default) (i386) [ ] Support for paging of anonymous memory (swap) Processor type and features ---> [ ] Symmetric multi-processing support Device Drivers ---> Networking support ---> [ ] Networking support SCSI device support ---> 今回は MPT SCSI デバイス <*> SCSI device support <*> を使用している為この設定 SCSI disk support Fusion MPT device support ---> を行っている。 <*> Fusion MPT (base + ScsiHost) drivers File systems ---> すべての項目を外し[ ]の状態にする # make bzImage 作成したカーネルのコピー(名前を変更してコピーする。) # cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.9-minik # cp arch/i386/boot/compressed/vmlinux.bin /boot/vmlinux.bin-2.6.9-minik (4) ダンプパーティションの作成 ダンプの採取先として用意したディスク上に、搭載メモリの 1.5 倍程度のダンプパ ーティションを作成する。ここでは/dev/sdb1 をディスクダンプ用のパーティショ ンとする。作成後、ダンプパーティションのメジャー番号とマイナー番号の確認を 行う。 # ls –l /dev/sdb1 brw-rw---- 1 root disk 8, 1 Jun 24 12:59 /dev/sdb1 メジャー番号 : 8 マイナー番号 : 1 となる。 (5) /boot/grub/menu.lst の追加変更 作成したミニカーネルが正しく稼動するか確認するために、grub にミニカーネルの 項目を追加する。 title Linux-2.6.9-minik kernel (hd0,0)/vmlinuz-2.6.9-minik mem=8M dump_dev=0x800001 dump_dev の”8”がメジャー番号、”1”がマイナー番号になる。 - 3-149 - テストの為、ミニカーネルを起動してダンプ採取後リブートするかを確認する。 (6) mkexec のパッチ適用 # tar zxvf mkexec-2.6.9-1.0.taz # tar jxvf linux-2.6.9.tar.bz2 # mv linux-2.6.9 linux-2.6.9-mkexec # cd linux-2.6.9-mkexec # patch -p1 < ../mkexec/PATCH/mkexec-v1.patch (7) mkexec の作成 # make menuconfig make 中に smp でエラーに Processor type and features ---> なる場合の対応 [ ] Symmetric multi-processing support Device Drivers ---> SCSI device support make で Qlogic エラーとな ---> SCSI low-level drivers る場合の対応 ---> Qlogicのものすべて外す # make ; make modules_install ; make install 設定完了後リブートし mkexec を起動する。 # reboot 起動後、カーネルが 2.6.9-mkexec であることを確認する。 # uname –r 2.6.9-mkexec (8) mkexec.ko の作成 mkexec/kernel/Makefile.base を編集し自分の環境に合わせる。 KVER= 2.6.9-mkexec KDIR= <mkdumpを導入したディレクトリ>/linux-2.6.9-mkexec KMODDIR= /lib/modules/2.6.9-mkexec make の準備 # cd <mkdumpを導入したディレクトリ>/mkexec # ln -s asm-i386 include/asm make の実行 # make ARCH=i386 - 3-150 - mkexec/kernel/mkexec.ko が作成される。 ■ 動作確認 (1) ミニカーネルダンプの実行 mkexec.ko のロード # insmod <mkdumpを導入したディレクトリ>/mkexec/kernel/mkexec.ko (2) ダンプを行う準備 /proc/mkexec の各項目にパラメータを入れる。 # echo 8 > /proc/mkexec/mem # echo “0x800001” > /proc/mkexec/dumpdev # echo “/boot/vmlinux.bin-2.6.9-minik” > /proc/mkexec/path # echo 1 > /proc/mkexec/stats (3) ダンプの採取 mkexec がロードされたこの状態で、カーネルパニックが発生すると、ミニカーネ ルが実行される。 テストのために、次の入力で、ミニカーネルを実行させることができる。 # echo 2 > /proc/mkexec/stats ダンプを実行した後、起動画面に戻り mkexec をインストールしたカーネルで正常 起動することを確認する。 (4) ダンプフォーマットの変換 ダンプパーティションに保存されたダンプを LKCD フォーマット形式のファイル に変換する。 変換ツールの作成 # cd /usr/src # tar zxvf mkd_conv.taz # cd mkd_conv # make elf2lkcd_i386、mkd2lkcd_i386、mkd2lkcd_x86_64 が作成される。 ・elf2lkcd_i386 i386 の vmcore フォーマットを LKCD フォーマットへ変換 ・mkd2lkcd_i386 i386 の mkdump フォーマットを LKCD フォーマットへ変換 ・mkd2lkcd_x86_64 x86_64 の mkdump フォーマットを LKCD フォーマットへ変換 ダンプフォーマットの変換実行 # ./mkd2lkcd_i386 /dev/sdb1 <dump-file> ダンプパーティション /dev/sdb1 に保存されていたダンプがファイルに変換される。 - 3-151 - 3.6.1.6 ダンプ採取ツールの評価 前項までに記述したdiskdump、netdump、LKCD、kdump、mkdumpを実際に使用して ダンプを採取し、その機能および操作性について評価を行った。ただし、各ダンプ採取ツ ールの機能についてソースコードレベルでの調査は行っていない。 各ダンプ採取ツールの比較(2005年9月時点)を表 3.6-1に示す。 表 3.6-1 ダンプ採取ツールの比較(その1) 項目 2005 年 9 月時点 diskdump netdump LKCD kdump mkdump ○(update3 以 ○(IA64 は × × × 降) update5 以降) RHEL4.0 ○ ○ × × × SLES8 × ○ ○ × × SLES9 × ○ ○ × × ○(SP1 以降) ○ × × × × ○ × × 1.0.1-5 0.7.7-3 6.1.0 1.101 2.0 netdump netdump LKCD ELF LKCD 収録ディストリビューシ RHEL3.0 ョン MIRACLE LINUX V3.0 ○(SP1 以降) Turbolinux10S 最新バージョン ダンプファイル形式 (手動変換が必 要) 対応解析ツール 採取トリガー crash ○ ○ ○ × ○ lcrash ○ ○ ○ × ○ Alicia ○ ○ ○ × ○ gdb - - - ○ - oops ○ ○ ○ ○ ○ NMI watchdog ○ ○ ○ ○ ○ SysRq マ ジ ッ ク キ ー ○ ○ ○ ○ ○ 実行コンテキスト ○ ○ ○ ○ ○ メモリ ○ ○ ○ ○ ○ キャッシュメモリ × × × × × スワップ領域 × × × × × 手動 自動 自動/手動を設定 手動 自動 (手動) 採取可能な情報 ダンプ採取による停止 後の再起動 可能 - 3-152 - 表 3.6-1 ダンプ採取ツールの比較(その2) 2005 年 9 月時点 項目 diskdump netdump LKCD kdump mkdump ダンプファイルの 保存されるタイミ ング クラッシュ時にダン プ用パーティション にダンプイメージを 自動採取後、再起 動時に自動的に起 動されるシェルにて 解 析 ツ ール で 参 照 可能な形式に変換 して保存される。 クラッシュ時に自動 的にサーバ側への 転送が開始される。 転送完了時点でサ ー バ の /var/crash 配下のディレ クトリ に解析ツールで参 照可能な形式で保 存される。 クラッシュ時にダン プ用パーティション にダンプイメージを 自動採取後、再起 動時に自動的に起 動されるシェルにて 解析ツー ルで 参照 可能な形式に変換 して保存される。 セカンドカーネル起 動後手動にてダン プファイルを保存す る。 対応インタフェー ス 以下のドライバを使 用するデバイスが 対応 以下のドライバを使 用する NIC が対応 カーネルに含まれる ディ スク ドライ バに は基本的に対応 カーネルに含まれる デ ィ スク ド ライ バ に は基本的に対応 セカンドカーネル起 動時に自動でダン プ用パーティション にダンプイメージを 採取。再起動後に 手動で変換 ツール を使用して解析ツー ルで参照可能な形 式のファイルに変換 する。 カーネルに含まれる デ ィ スク ド ライ バ に は基本的に対応 aic7xxx e1000 aic79xx tg3 mptfusion bcm5700 Red Hat 以外のディ ストリビューションに はパッケージが含ま れており、カーネル 再構築が必要な kdump、 mkdump よ りも設定が容易。ダ ンプ採取後の再起 動の有無やダンプ ファイルの圧縮保存 等を設定により変更 可能。 ・ダンプイメージ採 取のために物理メ モリサイズ以上の 領域を持つディスク デバイスまたはパ ーティションが必 要。スワップの情報 も採取可能である。 障害が発生したの とは別のカーネルに よりダンプイメ ージ を採取するので確 実性が高い 障害が発生したの とは別のカーネルに よりダンプイメ ージ を採取するので確 実性が高い ・標準で収録されて いるディストリビュー ションが無いのでカ ーネルへのパッチ 適用およびカーネ ル再構築が必要 ・セカンドカーネル 起動後に手動にて 操作を行う必要が る。 ・標準で収録されて いるディストリビュー ションが無いのでカ ーネルへのパッチ 適用およびカーネ ル再構築が必要 ・LSI53C1030 チップ を使用した SCSI カ ードでダンプが採取 できない現象が発 生しているが、原因 不明。 megaraid ata_pix 特徴 留意点 sata_promise Red Hat, MIRACLE LINUX にはパッケ ージが含まれてお り、カーネル再構 築が必要な kdump、mkdump よ りも設定が容易 ・ダンプイメージ採 取の為に物理メモリ サイズ以上の領域 を持つディスクデバ イスまたはパーティ ションが必要。 ・対応インタフェース に記載したドライバ を使用するディスク 以外は採取できな い。 Red Hat, MIRACLE LINUX にはパッケ ージが含まれてお り、カーネル再構 築 が 必 要 な kdump、mkdump よ りも設定が容易 ・ダンプを採取する マシンとは別にダン プを保存する為の サーバが必要とな る。 ・ NIC ド ラ イ バ が netdump に対応して いる必要がある。 ・Teaming を行って いる NIC は dump 送 信用としては使用で きない。 ・ network 経 由 で UDP プロトコルにて 転送されるので転 送中にデータを喪 失する可能性があ る。 - 3-153 - ■対応ディストリビューションによる比較 kdump および mkdump は標準で対応しているディストリビューションが現時点では 無い。したがってダンプ採取を行う為にはカーネルへのパッチの適用とカーネル再生成 が必要となる。LKCD は SLES(SUSE Linux Enterprise Server)、MIRACLE LINUX、 Turbolinux が対応しており、diskdump、netdump は RHEL、ML3.0 SP1 が対応して いる。 ■対応解析ツールによる比較 kdump は crash、lcrash では解析することができず、gdb での解析となる。それ以外 のダンプ採取ツールで採取したダンプファイルはダンプ解析ツール crash または lcrash で解析することが可能である。(Alicia は内部的に crash、lcrash のどちらもラ ッピングしており、kdump 以外の全てに使用可能である。) ■採取トリガーによる比較 いずれのダンプ採取ツールも oops、NMI、SysRq マジックキーのいずれかをトリガー としてダンプ採取が可能である。 ■採取可能な情報 いずれのダンプ採取ツールでも実行コンテキスト、メモリ等についての情報採取が可 能である。 ■ダンプ採取後の再起動 mkdump、netdump はダンプ採取後自動的にカーネルが再起動される。 kdump はセカンドカーネルが起動した状態でコンソールからの操作待ちの状態とな るため、手動によるダンプ採取後に再起動が必要である。 diskdump は、ダンプイメージをディスクへ出力した後、halt にて停止した状態とな るため、手動による再起動が必要である。 LKCD は設定により、ダンプ採取後に自動で再起動を行うか否かを設定可能である。 ■ダンプファイルの保存されるタイミング netdump はクラッシュ時にダンプ解析ツールで参照可能な形式でダンプファイルが保 存される。 diskdump 、LKCD はクラッシュ時にダンプイメージがディスクに書き込まれ、再起動 時にダンプ解析ツールで参照可能な形式に変換されて保存される。 mkdump はクラッシュ後のセカンドカーネル起動時にダンプイメージがディスクに採 取される。再起動後に手動にてファイル形式変換ツールによりダンプ解析ツールで参照 可能な形式に変換する必要がある kdump はクラッシュ後のセカンドカーネル起動時に自動でダンプの採取は行わない為、 セカンドカーネルが起動した状態で手動にてダンプファイルを保存する必要がある。 - 3-154 - ■対応インタフェースによる比較 kdump、mkdump、LKCD は基本的にカーネルに含まれるディスクのドライバに対応 している。 diskdump は diskdump 対応コードの入ったドライバを使用するディスクのみダンプ 採取が可能である。 netdump は netdump 対応ドライバを使用する NIC 経由でのみダンプ採取が可能であ る。 3.6.1.7 ダンプ採取ツールの考察 ダンプ採取ツールを選択するにあたってはいくつかの基準が考えられる。この項では、 3.6.1.6項で述べた比較を元に、それらの基準のうち、ダンプ採取の確実性、採取ツール導 入の容易性、ダンプ採取の容易性、ダンプ採取後の再起動の有無といった点について考察 を行う。尚、各項目の見出し後の括弧内には3.6.1.6項の表3.6-1で関連する項目を記した。 ■ダンプ採取の確実性 (ダンプファイルの保存されるタイミング、特徴) 障害発生時にメモリダンプが確実に採取できるかどうか、また採取した内容が信頼で きるか否かをダンプ採取に使用するカーネルの点から考える。 kdump および mkdump は、クラッシュ発生時にダンプ採取の為のカーネル(セカン ドカーネル)をそれまで稼働していたカーネル(ファーストカーネル)とは別のメモリ 空間に展開し、そのセカンドカーネルの制御によりダンプ採取を行う。これに対して、 diskdump、netdump、LKCD は、クラッシュが発生したカーネル自身の制御のもとに ダンプ採取を行う。 セカンドカーネルを使用する方法は、 “ダンプを採取するような状況に陥ったカーネル 自身をダンプ採取のために使用する”という diskdump、netdump、LKCD の仕組みが 持つ構造的な問題を回避するのに有効な方法であり、現時点で存在する Linux のカーネ ルダンプ採取としては、ダンプ採取の確実性および採取したダンプ内容の信頼性を高め るという点で、セカンドカーネルを使用する kdump、mkdump に圧倒的な優位性が認 められる。 ■ダンプ採取ツール導入の容易性 (収録ディストリビューション、留意点) セカンドカーネルを使用する方法は、現在の主なディストリビューションが標準で対 応していない。その為、kdump および mkdump を使用するためにはユーザもしくはユ ーザサポートを行うベンダが、パッチの適用およびカーネル再生成を行いシステムに適 用する必要がある。また、ユーザがカーネルにダンプ採取用のパッチを適用して使用す ると、カーネルに起因する障害が発生した場合にディストリビューション・ベンダのサ ポートが受けられなくなる事も考えられる。 このような点を考慮すると、セカンドカーネルを使用する方法はダンプ採取ツールの 機能としての利点は大きいが、Linux をシステムの一部として使用するユーザの立場か ら見れば導入は容易ではない。これに対し diskdump、netdump、LKCD は標準で各デ ィストリビューションが対応しており、パッケージの導入および設定方法も kdump、 - 3-155 - mkdump に比較して容易である。 ■ダンプ採取の容易性 (ダンプの保存されるタイミング、留意点) ユーザ環境でシステムが稼働している状態でカーネルがクラッシュした場合を考え ると、ダンプ採取の確実性と同時に、ダンプが容易に採取できる事。つまりダンプ採取 の容易性にも注目する必要がある。この点では、mkdump、LKCD、diskdump、netdump は障害発生時に手動の操作を必要とせずに自動的にダンプが採取されるためダンプ採取 は容易だといえる。これに対し、kdump はクラッシュ時にセカンドカーネルが起動して コンソールからの入力が可能となった時点で、手動でダンプ採取を行う必要がある。 kdump の今後の改善を期待したい。 ■ダンプ採取後の再起動 (ダンプ採取による停止後の再起動) ダンプ採取ツールの動作を考える時に、ダンプを採取するまでの動作とともに、ダン プ採取後にカーネルが自動で再起動されるか否かは大きな運用ポイントとなる。 システムとしての復旧を最優先しダウンタイムを極力短くしたいシステムにおいては、 ダンプ採取後に速やかにカーネル再起動を行い、業務を再開することが求められる。ハ ードウェアが原因の場合、再起動を行っても再度クラッシュが発生して結果的に最初の 障害発生時のダンプを消失するような事も考えられる。 このようにダンプ採取後に再起動するのが適当か否かは、システムの使用目的や冗長 構成の有無、障害発生原因がハードウェアによるものかソフトウェアによるものなのか により異なる為、ダンプ採取ツールに求められる機能としては LKCD のようにダンプ採 取後の自動的な再起動の有無を設定により選択可能とすることが望ましい。このような 機能は、LKCD が実運用を強く意識して開発されたことを示すものであり、他のダンプ 採取ツールにも、是非反映させたい機能である。 表 3.6-2 ダンプ採取ツールの比較・考察 項目 diskdump netdump LKCD kdump mkdump ダンプの確実性 × × × ○ ○ ダンプ採取ツール導入の ○ ○ ○ × × ○ △ ○ × ○ ○ × ○ 容易性 ダンプ採取の容易性 (サーバが必要) ダンプ採取後の再起動 △ ○ (手動再起動) ■今後の方向性 今後ミッションクリティカルな分野において Linux を使用する機会は増大し、障害発 - 3-156 - 生時にダンプを採取することの重要性はますます高まっていくと考えられる。ミッショ ンクリティカル環境では、セカンドカーネルによるダンプ採取が必須である、各ディス トリビューションがそれをサポートする事によってダンプ採取ツール導入の容易性を高 める事が必要である。また、ミッションクリティカルに特化して考えるならば、ダンプ 採取にカーネルの機能を使用する現在のソフトウェア的なアプローチとは別に、メイン フレーム等が持つハードウェア的な仕組みをエンタープライズサーバの必須機能として 組み込み、メモリダンプ採取を確実に行えるようにする方法等も、今後、検討の余地が あるだろう。 - 3-157 - 3.6.2 ダンプ解析ツール 3.6.2.1 ツール概要 今回、調査対象としたダンプ解析ツールの概要を次に示す。 ■crash crash は、UNIX の crash ツールのインターフェースをベースに作成されたツールである。 ライブメモリ(稼動中のメモリ)、netdump/diskdump で採取されたカーネルダンプ、 LKCD (Linux Kernel Crash Dump)で採取されたカーネルダンプに対応している。 GDB(GNU Debugger)をラッピングしているため、GDB のコマンドも実行でき、また、 コマンドラインには GNU Readline を採用していたり、ページャなども外部のコマンドを 利用していたりと、lcrash のように独自で全てを抱え込むという仕様にはなっていない。 また、ダンプ編集のスピードアップの考慮や、C プログラミングでの動的ライブラリによ る拡張コマンドの追加機能も備えている。 ■lcrash lcrash は、LKCD で採取されたダンプを編集するために作成されたツールである。 最新バージョンでは、netdump フォーマットに対応したため、crash と同等のダンプの 解析が行える。 カーネルのシンボル情報を得るのにデバッグオプション付きでコンパイルされたカーネ ルを必要としない、また、異なるアーキテクチャ上で採取されたダンプにも対応できるよ うになっている。 独自で sial というライブラリをもち、C 言語に非常に似た記述方法で作成したスクリプ トをインタプリタとして動かせるエンジンを持っている。 ■Alicia Aliciaは、既存のLinuxカーネルダンプ解析ツールであるcrash/lcrashをラッピングした ダンプ解析ツールであり(Alicia version1.1.0からlcrashにも対応)、Perl Shellを実装する。 これにより、Perl言語での解析スクリプト(LDAS)の作成と実行、Alicia標準関数による メモリの参照、既存のcrashでの解析、などが実現される。 また、作成した解析スクリプトを残し、解析者同士で共有することにより、解析時間の短 縮や、カーネル教育用の資料としても利用できる。 ■mdb mdb は、Solaris オペレーティングシステム用の汎用デバッグツールである。Solaris 8 からカーネルデバッグツールの crash は mdb に変更され、mdb は一般モジュールとカーネ ルの双方にデバッグ可能なデバックツールとして提供された。 - 3-158 - 表 3.6-3 ダンプ解析ツール一覧 crash lcrash Alicia mdb Linux Linux Linux Solaris UNIX SVR 系の LKCD で採取された crash/lcrash を ラ ッ UNIX の adb、 crash crash ツールのインタ ダンプを編集するた ピングしたダンプ解 コマンドの多くを提 ーフェースをベース めに作成されたツー 析ツール 供(Solaris に作成されたツール ル 解析 ・ライブメモリ ・ライブメモリ ・ライブメモリ ・ライブメモリ 対象 ・LKCD ・LKCD ・LKCD ・モジュール (Linux Kernel Crash (Linux Kernel Crash (Linux Kernel Crash ・core ダンプ Dump)で作成された Dump)で作成された Dump)で作成された ・カーネルダンプ カーネルダンプ カーネルダンプ カーネルダンプ ・netdump で作成さ ・netdump フォーマ ・netdump で作成さ れたカーネルダンプ ットにも対応をする れたカーネルダンプ 対応 OS 起源 8 から crash→mdb に) ようになった 使用可(gdb) 使用不可 使用可(crash の gdb) 使用可(mdb) コ マ ン 50 程度(gdb(400 程 50 程度 20 程度(crash/lcrash ド の 種 度)は含まない) デ バ ッ ガ 500 程度 コマンドは含まない) 類 コ マ ン C プログラミングに sial マクロを使用し、 Perl 言語での解析ス mdb デバッガモジュ ド の 拡 より新しいコマンド C 言語に非常に似た クリプト(LDAS)に ール API が提供され 張 作成が可能 記述方法でコマンド よりコマンド作成が ており、C 言語のプロ 作成が可能 可能 グラミングによりコ マンド作成が可能 その他 ・コマンドラインには ・ダンプ編集にあたっ ・reboot に「-d」フ GNU Readline を採 て、カーネルのシンボ ラグを設定してシス 用。ページャなども外 ル情報を得るのにデ テムを再起動すると、 部のコマンドを利用 バッグオプション付 カーネルが強制的に している きでコンパイルされ パニック状態になり、 ・ダンプ編集にあたっ たカーネルを必要と クラッシュダンプが て、カーネルのシンボ しない 保存される。 ル情報を得るのにデ ・異なるアーキテクチ バッグオプション付 ャ上で採取されたダ きでコンパイルされ ンプにも対応できる たカーネルが必要 - 3-159 - 3.6.2.2 crash/lcrash/Alicia の比較 Linuxのダンプ解析ツールであるcrash/lcrash/Aliciaをコマンドレベルで比較したのが 表 3.6-4 である。 比較に用いたバージョンは以下のとおりである。 crash :Ver 3.8.5 lcrash :Ver 0.9.2 Alicia :Ver 1.1.0 表 3.6-4 crash crash/lcrash/Alicia コマンドマッピング表 lcrash Alicia コメント * -- * ポインタへのショートカット !command -- !command シェルへのエスケープおよびコマンドを実行する alias -- alias コマンド別名を設定する ascii -- ascii 16 進法のストリングを ASCII に変換する bt bt trace t strace rd bt trace t strace rd バックトレース(スタックトレース)を表示する デフォルト CPU のレジスタ情報を表示する btop -- btop 16 進アドレスとそのページ番号に変更する dev -- dev デバイスデータを表示する dis dis id dis id 逆アセンブルを行う print p pb,pd,po,px base eval -p pb,pd,po,px base 評価をおこなう 2、8、10、16進数の値を表示する exit quit q, q! デバッガを終了する load extend -- コマンドセットの拡張 sial マクロをロードする files -- files オープン・ファイルを表示する foreach -- foreach システムのマルチタスクへのコマンドデータの表示を指 示する fuser -- fuser 指定されたファイルのユーザを表示する eval exit quit q, q! extend - 3-160 - crash lcrash Alicia コメント gdb -- gdb gdb コマンドを実行する help help ? version help ? version 使用可能なコマンドの一覧を表示する lcrash のバージョン情報を表示する irq -- irq IRQ を表示する kmem -- kmem カーネルメモリ情報を表示する list walk list walk リンクしたリストを表示する log -- log ダンプ・システム・メッセージ・バッファを表示する mach -- mach マシン固有のデータを表示する mod module mod module モジュール情報およびシンボルとデバッグするデータの ロードをおこなう ロードしたモジュールまたはモジュールシンボルを表示 する mount -- mount マウントされているファイルシステムに関する情報を出 力する net -- net ネットワーク情報を表示する p print p pb, pd, po, px -p pb, pd, po, px 値を表示する ps ps ps アクティブプロセスを出力する pte -- pte ページテーブルエントリを変換する ptob -- ptob ページフレーム番号をそのバイト値に変換する ptov -- ptov 16 進物理アドレスをカーネルの仮想アドレスに変換する rd dump md od rd dump md od 指定された領域の書式付きメモリーダンプを出力する repeat -- repeat コマンドを繰り返す runq -- runq ランキュー上のタスクを表示する search -- search カーネルのアドレス空間で特定の値を検索する set set deftask set deftask プロセス情況または内部クラッシュ変数をセットする デフォルトの task をセット、または、デフォルトの task のアドレスを表示する - 3-161 - crash lcrash Alicia コメント sig -- sig タスクシグナルハンドリング struct -- struct 構造体の内容を表示する swap -- swap スワップ情報を表示する sym findsym fsym symbol sym findsym fsym symbol シンボルをその仮想アドレスに変換する、またはその逆 シンボリックネーム/アドレスの関連情報を表示する sys stat info main sys stat info main システム情報を表示する task task task タスク構造の内容 timer -- timer タイマキューデータ union -- union union 構造体の内容 vm -- vm 仮想メモリ情報を表示する vtop vtop vtop 仮想アドレスを物理アドレスに変換する waitq -- waitq 待機キューリスト上のタスクリストを表示する whatis whatis whatis データのシンボルテーブルまたは型情報を表示する wr -- wr メモリへの書き込み q quit q, q! quit q, q! デバッガを終了する -- defcpu defcpu デフォルトの CPU をセット、または、デフォルトの CPU を表示する -- history -- コマンドヒストリーをセットまたは表示する -- ldcmds ldcmds 動的にライブラリをロードする -- mktrace mt mktrace mt スタックトレースを生成する -- mmap mmap mmap_list 内のエントリの関連情報を表示する -- namelist nmlist namelist nmlist オープンしたネームリストをリストする/追加する -- page page page_list 内のエントリのページ構造から関連情報を表 示する -- report -- crash dump report (kernel failure が起こったときのシ ステムの状態等)を表示する - 3-162 - crash lcrash Alicia コメント -- savedump savedump ライブダンプを生成する、または、ダンプサイズを小さく する -- sizeof offset sizeof offset バイト単位のデータタイプのサイズを表示し、加えて、構 造体メンバへのオフセットを表示する -- symtab symtab シンボルテーブル情報を追加/削除/リストする -- unload unload sial マクロをアンロードする -- vi -- (!vi) vi セッションを開始する -- -- kernel メモリ内容を参照する -- -- get_mem 指定したアドレスの内容を参照する -- -- get_addr 指定したカーネル変数のアドレスを参照する -- -- get_value 指定したカーネル変数の内容を参照する -- -- get_increment 開いているダンプのワードサイズ(バイト)を得る -- -- less 引数を less ページャで参照する -- -- more 引数を more ページャで参照する -- -- list_h 環状の list_head リンクをたどりリンク上のすべての構造 体アドレス配列を返す(LDAS) -- -- list_c 親構造体の配下の子構造体の list_head リンクをたどりリ ンク上のすべての構造体のアドレス配列を返す(LDAS) -- -- list_s 入力されたアドレスからの list_head リンクをたどり、リ ンク上のすべての構造体アドレス配列を返す(LDAS) -- -- list_foreach 入力された配列内のアドレスの構造体アドレスと特定の メンバの値を一覧表示する(LDAS) -- -- list_task_vma 入力されたプロセスの仮想メモリ空間を一覧表示する (LDAS) -- -- task_dentries 入力されたプロセスがアタッチしているすべてのファイ ル dentry 構造体のアドレスの配列を返す(LDAS) -- -- dentry_parents 入力された dentry の親の dentry を/(ルート)までたどり dentry 構造体のアドレスの配列を返す(LDAS) -- -- get_dentry 入力されたフルパスのディレクトリまたはファイルの dentry 構造体のアドレスを返す(LDAS) -- -- get_task 入力された PID を持つ task_struct 構造体のアドレスを返 す(LDAS) -- -- ts インタラクティブに task_struct 構造体のメンバの値を表 示できる(LDAS) - 3-163 - crash -- lcrash Alicia -- report コメント 初期解析用レポート作成を行う コマンドレベルで crash と lcrash を比較すると crash は gdb もラッピングしておりコマ ンド数も多く充実している。Alicia は crash/lcrash をラッピングしているため crash/lcrash コマンドはほとんどサポート可能であり、さらに独自のコマンドが追加されている。ただ し、起動時に crash または lcrash を選択し使用するため、一度に双方のコマンドを使用す ることはできない。 3.6.2.3 crash/lcrash コマンドと mdb コマンドとの網羅性の比較 他の OS との比較ということで Solaris のダンプ解析ツールである mdb に対してコマン ドレベルでの比較をおこなった。mdb は一般モジュールのデバッガを兼ねているため、コ マンド数が非常に多い。比較を行うにあたり、mdb の全てのコマンドを対象に比較を行う とわかりづらいため、2つの切り口で比較を行った。 一つ目として 表 3.6-5 では、crash/lcrashのコマンドが表示可能な情報をmdbがどの程度網 羅しているかという視点で比較した。 比較に用いた各ツールのバージョンは以下のとおりである。 crash :Ver 3.8.5 lcrash :Ver 0.9.2 mdb :Solaris 表 3.6-5 crash 10 crash/lcrash と mdb コマンドマッピング表 lcrash mdb コメント * -- -- ポインタへのショートカット !command -- !command シェルへのエスケープおよびコマンドを実行する alias -- -- コマンド別名を設定する ascii -- -- 16 進法のストリングを ASCII に変換する bt bt trace t strace rd stack regs $c、$C バックトレース(スタックトレース)を表示する デフォルト CPU のレジスタ情報を表示する btop -- -- 16 進アドレスとそのページ番号に変更する dev -- devnames prtconf デバイスデータを表示する - 3-164 - crash lcrash mdb コメント dis dis id dis 逆アセンブルを行う eval print p pb,pd,po,px base eval 評価をおこなう 2、8、10、16進数の値を表示する exit quit q, q! quit デバッガを終了する extend load $<< load コマンドセットの拡張 sial マクロをロードする files -- -- オープン・ファイルを表示する foreach -- -- システムのマルチタスクへのコマンドデータの表示を 指示する fuser -- -- 指定されたファイルのユーザを表示する gdb -- -- gdb コマンドを実行する help help ? version dcmds 使用可能なコマンドの一覧を表示する lcrash のバージョン情報を表示する irq -- -- IRQ を表示する kmem -- kmalog kmastat kmausers kmem_cache kmem_log kmem_verify カーネルメモリ情報を表示する list walk walk リンクしたリストを表示する log -- -- ダンプ・システム・メッセージ・バッファを表示する mach -- cpuinfo マシン固有のデータを表示する mod module ctfinfo modinfo modctl モジュール情報およびシンボルとデバッグするデータ のロードをおこなう ロードしたモジュールまたはモジュールシンボルを表 示する mount -- fsinfo マウントされているファイルシステムに関する情報を 出力する net -- netstat tcpb ネットワーク情報を表示する - 3-165 - crash lcrash mdb コメント p print p pb, pd, po, px -- 値を表示する ps ps ps ptree アクティブプロセスを出力する pte -- -- ページテーブルエントリを変換する ptob -- -- ページフレーム番号をそのバイト値に変換する -- -- 16 進物理アドレスをカーネルの仮想アドレスに変換す る rd dump md od dump 指定された領域の書式付きメモリーダンプを出力する repeat -- -- コマンドを繰り返す runq -- -- ランキュー上のタスクを表示する search -- kgrep カーネルのアドレス空間で特定の値を検索する set set deftask -- プロセス情況または内部クラッシュ変数をセットする デフォルトの task をセット、または、デフォルトの task のアドレスを表示する sig -- -- タスクシグナルハンドリング struct -- offsetof 構造体の内容を表示する swap -- swapinfo スワップ情報を表示する sym findsym fsym symbol nm シンボルをその仮想アドレスに変換する、またはその 逆シンボリックネーム/アドレスの関連情報を表示す る sys stat info main status システム情報を表示する task task task task_entry タスク構造の内容 timer -- -- タイマキューデータ union -- offsetof union 構造体の内容 vm -- -- 仮想メモリ情報を表示する vtop vtop vtop 仮想アドレスを物理アドレスに変換する waitq -- queue 待機キューリスト上のタスクリストを表示する whatis whatis whatis データのシンボルテーブルまたは型情報を表示する ptov - 3-166 - crash lcrash mdb コメント wr -- -- メモリへの書き込み q quit q, q! quit デバッガを終了する -- defcpu -- デフォルトの CPU をセット、または、デフォルトの CPU を表示する -- history -- コマンドヒストリーをセットまたは表示する -- ldcmds -- 動的にライブラリをロードする -- mktrace mt -- スタックトレースを生成する -- mmap -- mmap_list 内のエントリの関連情報を表示する -- namelist nmlist -- オープンしたネームリストをリストする/追加する -- page page page_list 内のエントリのページ構造から関連情報を 表示する -- report -- crash dump report (kernel failure が起こったときの システムの状態等)を表示する -- savedump -- Live dump を生成する、または、ダンプサイズを小さ くする -- sizeof offset sizeof バイト単位のデータタイプのサイズを表示し、加えて、 構造体メンバへのオフセットを表示する -- symtab -- シンボルテーブル情報を追加/削除/リストする -- unload unload sial マクロをアンロードする -- vi -- vi セッションを開始する crash/lcrash のコマンドのほとんどは mdb にも存在するが、files(オープン中のファイ ルの表示)/irq(IRQ 情報の表示)/runq(RUNQ 情報の表示)等 crash にしか存在しない コマンドも存在する。また、report のように一つのコマンドで crash dump report 情報を 表示できるのは lcrash のひとつの特徴である。 操作性としては、mdb はコマンドに“::”が必要で、慣れてしまえば問題ないのかも しれないが、crash/lcrash と比較すると使いにくく感じた。 - 3-167 - 3.6.2.4 mdb コマンドと crash/lcrash コマンドとの網羅性の比較 「表3.6-5 mdbとcrash/lcrashコマンドマッピング表」ではmdbのコマンドのうちカーネ ルダンプ解析に使用するコマンドに対して、crash/lcrashのコマンドがどの程度網羅してい るかという視点で比較を行った。 比較に使用した各コマンドのバージョンは「3.6.2.3 crash/lcrashコマンドとmdbコマンド との網羅性の比較」と同一である。 表 3.6-6 区分 mdb mdb と crash/lcrash コマンドマッピング表 crash lcrash コメント (gdb) カーネルメモ リアロケータ dcmd allocdby -- -- 指定されたカーネルスレッドのアドレスを使用して、その スレッドが割り当てたメモリのリストを新しい順に出力 する dcmd bufctl -- -- 指定された bufctl address についての bufctl 情報の要約 を出力する dcmd findleaks -- -- フルセットの kmem デバッギング機能が有効になってい る場合に、カーネルクラッシュダンプ時に効率的にメモリ ーリークを検出する dcmd freedby -- -- 指定されたカーネルスレッドのアドレスを使用して、その スレッドが解放したメモリのリストを新しい順に出力す る dcmd kgrep search -- カーネルアドレス空間の中で、指定されたポインタサイズ 値を含んでいるポインタ整列アドレスを検索する dcmd kmalog kmem -- カーネルメモリーアロケータトランザクションログ内の イベントを表示する dcmd kmastat kmem -- カーネルメモリーアロケータキャッシュおよび仮想メモ リ領域のリストと該当する統計を表示する dcmd kmausers kmem -- カーネルメモリアロケータの現在のメモリ割り当てが中 程度あるいは多いユーザに関する情報を出力する dcmd kmem_cache kmem -- 指定されたアドレスに格納されている kmem_cache 構 造体、またはアクティブ kmem_cache 構造体の完全なセ ットをフォーマットして表示する dcmd kmem_log kmem -- kmem トランザクションログの完全なセットを新しい順 にソートして表示する dcmd kmem_verify kmem -- 指定されたアドレスに格納されている kmem_cache 構 造体、またはアクティブ kmem_cache 構造体の完全なセ ットの完全性を検証する dcmd vmem -- -- 指定されたアドレスに格納されている vmem 構造体、ま たはアクティブ vmem 構造体の完全なセットをフォーマ ットして表示する - 3-168 - 区分 mdb crash lcrash コメント (gdb) dcmd vmem_seg -- -- 指定されたアドレスに格納されている vmem_seg 構造体 をフォーマットして表示する dcmd whatis whatis (whatis) whatis 指定されたアドレスに関する情報をレポートする walk allocdby -- -- 指定された kthread_t 構造体のアドレスを開始点として 使用して、当該カーネルスレッドによって行われたメモリ 割り当てに対応する bufctl 構造体のセットに対して反復 適用する walk bufctl -- -- 指定された kmem_cache_t 構造体のアドレスを開始点と して使用して、このキャッシュに関連し割り当てられた bufctl のセットに対して反復適用する walk freectl ― -- 指定された kmem_cache_t 構造体のアドレスを開始点と して使用して、このキャッシュに関連する空き bufctl のセ ットに対して反復適用する walk freedby -- -- 指定された kthread_t 構造体のアドレスを開始点として 使用して、このカーネルスレッドによって行われたメモリ 割り当て解除に対応する bufctl 構造体のセットに対して 反復適用する walk freemem -- -- 指定された kmem_cache_t 構造体のアドレスを開始点と して使用して、このキャッシュに関連する空きバッファの セットに対して反復適用する walk kmem -- -- 指定された kmem_cache_t 構造体のアドレスを開始点と して使用して、このキャッシュに関連し割り当てられたバ ッファのセットに対して反復適用する Walk kmem_cache -- -- アクティブな kmem_cache_t 構造体のセットに対して反 復適用する walk kmem_cpu_cache -- -- 指定された kmem_cache_t 構造体のアドレスを開始点と して使用して、このキャッシュに関連する CPU ごとの kmem_cpu_cache_t 構造体に対して反復適用する walk kmem_slab -- -- 指定された kmem_cache_t 構造体のアドレスを開始点と して使用して、関連する kmem_slab_t 構造体のセットに 対して反復適用する walk kmem_log -- -- kmem アロケータトランザクションログに格納されてい る bufctl のセットに対して反復適用する walk leak -- -- 指定された bufctl 構造体のアドレスを使用して、同様な割 り当てスタックトレースを持つ、リークが発生したメモリ ーバッファに対応する bufctl 構造体のセットに対して反 復適用する - 3-169 - 区分 mdb crash lcrash コメント (gdb) ファイルシス テム 仮想メモリ walk leakbuf -- -- 定された bufctl 構造体のアドレスを使用して、同様な割り 当てスタックトレースを持つ、リークが発生したメモリー バッファに対応するバッファドレスのセットに対して反 復適用する dcmd fsinfo mount -- マウントされているファイルシステムのテーブルを表示 する dcmd lminfo -- -- ロックマネージャによって登録されたアクティブネット ワークロックを持つ vnode のテーブルを表示する dcmd vnode2path -- -- 指定された vnode アドレスに対応するパス名を表示する walk buf -- -- アクティブなブロック I/O 転送構造体 (buf_t 構造体) の セットに対して反復適用する dcmd addr2smap -- -- カーネルの segmap アドレス空間セグメント内の指定さ れたアドレスに対応する smap 構造体アドレスを出力す る dcmd as2proc -- -- as_t アドレス as に対応するプロセスの proc_t アドレスを 表示する dcmd memlist -- -- 指定された memlist 構造体または既知の memlist 構造体 の1つを表示する dcmd memstat -- -- システム全体のメモリ使用状況の要約を表示する dcmd page -- page 指定された page_t のプロパティを表示する dcmd seg -- -- 指定されたアドレス空間セグメント (seg_t アドレス) を フォーマットして表示する dcmd swapinfo swap -- アクティブな swapinfo 構造体すべて、あるいは指定され た swapinfo 構造体についての情報を表示する dcmd vnode2smap -- -- 指定された vnode_t アドレスおよびオフセットに対応す る smap 構造体アドレスを出力する walk anon -- -- 指定された anon_map 構造体のアドレスを開始点として 使用して、関連する anon 構造体のセットに対して反復適 用する walk memlist -- -- 指定された memlist 構造体のスパンに対して反復適用す る walk page -- -- すべてのシステムの page 構造体に対して反復適用する walk seg -- -- 指定された as_t 構造体のアドレスを開始点として使用し て、指定されたアドレス空間に関連するアドレス空間セグ メント (seg 構造体) のセットに対して反復適用する walk swapinfo swap -- アクティブな swapinfo 構造体のリストに対して反復適 用する - 3-170 - mdb 区分 crash lcrash コメント (gdb) CPU と デ ィ スパッチャ デバイスドラ イ バ と DDI フレームワー ク dcmd callout -- -- コールアウトテーブルを表示する dcmd class -- -- スケジューリングクラステーブルを表示する dcmd cpuinfo -- -- 各 CPU 上で現在実行されているスレッドのテーブルを 表示する walk cpu -- -- カーネル CPU 構造体のセットに対して反復適用する dcmd binding_hash_entry -- -- 指定されたカーネル名とメジャー番号のバインディング ハッシュテーブルエントリ (構造体 bind) のアドレスを 使用して、ノードバインディング名、メジャー番号、およ び次の要素へのポインタを表示する dcmd devbindings -- -- 名前を指定されたドライバについてすべてのインスタン スのリストを表示する dcmd devinfo -- -- devinfo ノードに関連するシステムプロパティ及びドライ バプロパティを出力する dcmd devinfo2driver -- -- devinfo ノードに関連するドライバ (もしあれば) の名前 を出力する dcmd prtconf dev -- devinfo で指定されたデバイスノードからカーネルデバイ スツリーを表示する dcmd major2name -- -- 指定されたメジャー番号に該当するドライバ名を表示す る dcmd modctl2devinfo -- -- 指定された modctl アドレスに対応するすべてのデバイ スノードを出力する dcmd name2major -- -- 指定されたデバイスドライバ名を使用して、そのメジャー 番号を表示する dcmd -- -- 指定された softstate 状態ポインタとデバイスインスタン ス番号を使用して、そのインスタンスのソフトの状態を表 示する walk binding_hash -- -- 指定されたカーネルバインディングハッシュテーブルエ ントリの配列 (構造体 bind **) のアドレスを使用して、ハ ッシュテーブル内のすべてのエントリを調べて、各構造体 bind のアドレスを戻す walk devinfo -- -- 最初に、指定された devinfo の親に対して反復適用し、そ れらを最下位から世代順に戻します。次に、指定された devinfo 自身を戻します。その次に、指定された devinfo の子に対して、世代順に最上位から最下位まで反復適用す る walk devinfo_children -- -- 最初に、指定された devinfo を戻し、次に、指定された devinfo の子に対して、世代順に最上位から最下位まで反 復適用する softstate - 3-171 - 区分 mdb crash lcrash コメント (gdb) STREAMS walk devinfo_parents -- -- 指定された devinfo の親に対して、世代順に最上位から最 下位まで反復適用する walk devi_next -- -- 指定された devinfo の兄弟に対して反復適用する walk devnames -- -- devnames 配列のエントリに対して反復適用する walk softstate -- -- 指定された softstate ポインタを使用して、ドライバ状態 構造体への NULL 以外のポインタをすべて表示する walk softstate_all -- -- 指定された softstate ポインタを使用して、ドライバ状態 構造体へのポインタをすべて表示する dcmd mblk2dblk -- -- 指定された mblk_t のアド レスを使用して、対応する dblk_t のアドレスを出力する dcmd mblk_verify -- -- 1 つまたは複数のメッセージブロックの整合性を確認す る dcmd queue waitq -- 指定された queue_t データ構造体をフィルタリングして 表示する dcmd q2syncq -- -- 指定された queue_t のアドレスを使用して、対応する syncq_t データ構造体のアドレスを出力する dcmd q2otherq -- -- 指定された queue_t のアドレスを使用して、ピアな読み 取りまたは書き込み待ち行列構造体のアドレスを出力す る dcmd q2rdq -- -- 指定された queue_t のアドレスを使用して、対応する読 み取り待ち行列のアドレスを出力する dcmd q2wrq -- -- 指定された queue_t のアドレスを使用して、対応する書 き込み待ち行列のアドレスを出力する dcmd stream -- -- 指定された STREAM ヘッドを表す stdata_t 構造体のア ドレスを使用して、カーネル STREAM データ構造体のイ メージ図を表示する dcmd syncq -- -- 指定された syncq_t データ構造体をフィルタリングし表 示する dcmd syncq2q -- -- 指定された syncq_t のアドレスを使用して、対応する queue_t データ構造体のアドレスを出力する walk b_cont -- -- 指定された mblk_t のアドレスを使用して、b_cont ポイ ンタに従いながら、関連するメッセージ構造体のセットに 対して反復適用する walk b_next -- -- 指定された mblk_t のアドレスを使用して、b_next ポイ ンタに従いながら、関連するメッセージ構造体のセットに 対して反復適用する - 3-172 - mdb 区分 crash lcrash コメント (gdb) ネットワーク 関連機能 ファイル、プ ロセス、およ walk qlink -- -- 指定された queue_t 構造体のアドレスを使用して、q_link ポインタを使用しながら、関連する待ち行列のリストを調 べる walk qnext -- -- 指定された queue_t 構造体のアドレスを使用して、q_next ポインタを使用しながら、関連する待ち行列のリストを調 べる walk readq -- -- 指定された stdata_t 構造体のアドレスを使用して、読み 取り側待ち行列構造体のリストを調べる walk writeq -- -- stdata を使用して、書き込み側待ち行列構造体のリストを 調べる dcmd mi -- -- 指定されたカーネル MI_O を使用して、MI_O またはその ペイロードをフィルタリングし表示する dcmd netstat net -- ネットワークの統計とアクティブな接続を表示する dcmd sonode -- -- sonode オブジェクトをフィルタリングし表示する dcmd tcpb net -- tcpb オブジェクトをフィルタリングし表示する walk ar -- -- 指定された ar のアドレスを使用して、指定された ar か ら最後の ar までのすべての ar オブジェクトを調べる walk icmp -- -- 指定された icmp のアドレスを使用して、指定された icmp から最後の icmp までのすべての icmp オブジェ クトを調べる walk ill -- -- 指定されたインタフェースリンク層構造体 (ill) のアドレ スを使用して、指定された ill から最後の ill までのすべ ての ill オブジェクトを調べる walk ipc -- -- 指定された ipc のアドレスを使用して、指定された ipc から最後の ipc までのすべての ipc オブジェクトを調 べる walk mi -- -- 指定された MI_O のアドレスを使用して、この MI 内に あるすべての MI_O を調べる walk sonode -- -- 指定された sonode を使用して、指定された sonode か ら始まる関連する sonode のリストを調べる walk tcpb -- -- 指定された MI を使用して、指定された tcpb から最後の TCP 接続までのすべての TCP 接続を調べる walk udp -- -- 指定された MI のアドレスを使用して、指定された udp か ら最後の udp までのすべての udp オブジェクトを調べ る dcmd fd -- -- 指定されたプロセスに関連するファイル記述子 fd-num に対応する file_t アドレスを出力する - 3-173 - 区分 mdb crash lcrash コメント (gdb) びスレッド 同期プリミテ ィブ dcmd findstack -- -- 指定されたカーネルスレッド (kthread_t 構造体の仮想ア ドレスによって識別される) に関連するスタックトレース を出力する dcmd pgrep -- -- 名前が regexp 正規表現パターンに適合するプロセスの プロセス情報を表示する dcmd pid2proc -- -- 指定されたプロセス ID に対応する proc_t アドレスを出 力する dcmd pmap -- -- 指定されたプロセスアドレスに該当するプロセスのメモ リマップを出力する dcmd ps ps -- 指定されたプロセスまたはすべてのアクティブなシステ ムプロセスに関連する情報の要約を ps に似た形式で出力 する dcmd ptree ps -- それぞれの親プロセスから派生した子プロセスを含むプ ロセスツリーを出力する dcmd task task task アクティブなカーネルタスク構造体とそれに関連する ID 番号および属性のリストを出力する dcmd thread -- -- 指定された kthread_t カーネル構造体のプロパティを表 示する dcmd whereopen -- -- 指 定 さ れ た vnode_t ア ド レ ス を 使 用 し て 、 現 在 こ の vnode を フ ァ イ ル テ ー ブ ル に 開 い て い る プ ロ セ ス の proc_t アドレスを出力する walk file -- -- 指定された proc_t 構造体のアドレスを開始点として使用 して、指定されたプロセスに関連し開いているファイル (file_t 構造体) のセットに対して反復適用する walk proc -- -- アクティブなプロセス (proc_t) 構造体に対して反復適用 する walk task task -- 指定されたタスクポインタを使用して、指定されたタスク のメンバであるプロセスの proc_t 構造体のリストに対し て反復適用する walk thread -- -- カーネルスレッド (kthread_t) 構造体のセットに対して反 復適用する dcmd rwlock -- -- 指定された読み取り書き込みロックのアドレスを使用し て、現在のロックの状態と待機しているスレッドのリスト を表示する dcmd sobj2ts -- -- 同期オブジェクトのアドレスを対応するターンスタイル のアドレスに変換して、ターンスタイルのアドレスを出力 する dcmd turnstile -- -- 指定された turnstile_t のプロパティを表示する - 3-174 - 区分 mdb crash lcrash コメント (gdb) dcmd wchaninfo -- -- 指定された条件変数またはセマフォのアドレスを使用し て、このオブジェクト上で現在待機しているスレッドを表 示する walk blocked -- -- 指定された同期オブジェクトのアドレスを使用して、ブロ ックされているカーネルスレッドのリストに対して反復 適用する walk wchan -- -- 指定された条件変数またはセマフォのアドレスを使用し て、ブロックされているカーネルスレッドのリストに対し て反復適用する dcmd cycinfo -- -- CPU ごとに cyclic サブシステムの各 CPU の状態を表 示する dcmd cyclic -- -- 指定されたアドレスの cyclic_t をフォーマットし、表示す る dcmd cyccover -- -- cyclic サブシステムのコードカバレッジ情報を表示する dcmd cyctrace -- -- cyclic サブシステムのトレース情報を表示する walk cyccpu -- -- 各 CPU の cyc_cpu_t 構造体に対して反復適用する walk cyctrace -- -- cyclic トレースバッファ構造体に対して反復適用する dcmd taskq_entry task -- 指定された taskq_entry 構造体の内容を出力する walk taskq_entry -- -- 指 定 さ れ た taskq 構 造 体 の ア ド レ ス を 使 用 し て 、 taskq_entry 構造体のリストに対して反復適用する dcmd errorq -- -- 指定されたエラー待ち行列に関連する情報の要約を表示 する walk errorq -- -- システムエラー待ち行列のリストを調べて、各エラー待ち 行列のアドレスを返す walk errorq_data -- -- 指定されたエラー待ち行列のアドレスを使用して、保留中 の各エラーイベントデータバッファのアドレスを返す 構成 dcmd system -- -- システム初期化中にカーネルが解析したときの system 構 成ファイルの内容を表示する プロセス間通 信のデバッギ ングサポート (ipc) dcmd ipcs -- -- 既知のメッセージ待ち行列、セマフォ、および共用メモリ セグメントに対応するシステム全体の IPC 識別子のリス トを表示する dcmd msg -- -- 指定されたメッセージ待ち行列要素 (構造体 msg) のプ ロパティを表示する dcmd msqid -- -- 指定されたメッセージ待ち行列 IPC 識別子を対応するカ ーネル実装構造体へのポインタに変換して、このカーネル 構造体のアドレスを出力する cyclic タスク待ち行 列 エラー待ち行 列 - 3-175 - 区分 mdb crash lcrash コメント (gdb) ループバック ファイルシス テムのデバッ ギングサポー ト (lofs) インターネッ トプロトコル モジュールの デバッギング サポート (ip) カーネル実行 時リンカーの dcmd msqid_ds -- -- 指 定 さ れ た msqid_ds 構 造 体 ま た は ア ク テ ィ ブ な msqid_ds 構造体 (メッセージ待ち行列識別子) のテーブ ルを出力する dcmd semid -- -- 指定されたセマフォ IPC 識別子を対応するカーネル実装 構造体へのポインタに変換して、このカーネル構造体のア ドレスを出力する dcmd semid_ds -- -- 指 定 さ れ た semid_ds 構 造 体 ま た は ア ク テ ィ ブ な semid_ds 構造体 (セマフォ識別子) のテーブルを出力す る dcmd shmid -- -- 指定された共用メモリ IPC 識別子を対応するカーネル実 装構造体へのポインタに変換して、このカーネル構造体の アドレスを出力する dcmd shmid_ds -- -- 指 定 さ れ た shmid_ds 構 造 体 ま た は ア ク テ ィ ブ な shmid_ds 構造体 (共用メモリーセグメント識別子) のテ ーブルを出力する walk msgqueue -- -- メッセージ待ち行列識別子に対応するアクティブな msqid_ds 構造体を調べる walk msq -- -- 現在指定されたメッセージ待ち行列に入っている message 構造体に対して反復適用する walk sem -- -- セマフォ識別子に対応するアクティブな semid_ds 構造 体を調べる walk shm -- -- 共用メモリセグメント識別子に対応するアクティブな shmid_ds 構造体を調べる dcmd lnode -- -- 指定された lnode_t 、また はカーネルの アクティブな lnode_t 構造体のテーブルを出力する dcmd lnode2dev -- -- 指定された lnode_t アドレスに対応する配下のループバ ックマウントファイルシステムの dev_t (vfs_dev) を出力 する dcmd lnode2rdev -- -- 指定された lnode_t アドレスに対応する配下のループバ ックマウントファイルシステムの dev_t (li_rdev) を出力 する walk lnode -- -- カーネルのアクティブな lnode_t 構造体を調べる dcmd ire -- -- 指定された ire_t、またはカーネルのアクティブな ire_t 構 造体のテーブルを出力する walk ire -- -- カーネルのアクティブな ire (Internet Route Entry) 構造 体を調べる dcmd modctl -- -- 指 定 さ れ た modctl 、 ま た は カ ー ネ ル の ア ク テ ィ ブ な modctl 構造体のテーブルを出力する - 3-176 - 区分 mdb crash lcrash コメント (gdb) デバッギング サ ポ ー ト (krtld) USB フ レ ー ムワークのデ バッギングサ ポート (uhci) USB フ レ ー ムワークのデ バッギングサ ポート (usba) dcmd modhdrs -- -- 指定された modctl 構造体のアドレスを使用して、モジュ ールの ELF 実行可能ヘッダーとセクションヘッダーを出 力する dcmd modinfo mod module アクティブカーネルモジュールに関する情報を出力する walk modctl mod -- カーネルのアクティブな modctl 構造体のリストを調べ る dcmd uhci_qh -- -- 指 定 さ れ た USB UHCI コ ン ト ロ ー ラ の QH (Queue Head) 構造体のアドレスを使用して、この構造体の内容を 出力する dcmd uhci_td -- -- 指定された USB UHCI コントローラの TD (Transaction Descriptor) 構造体のアドレスを使用して、この構造体の内 容を出力する walk uhci_qh -- -- 指 定 さ れ た USB UHCI コ ン ト ロ ー ラ の QH (Queue Head) 構造体のアドレスを使用して、このような構造体の リストに対して反復適用する walk uhci_td -- -- 指定された USB UHCI コントローラの TD (Transaction Descriptor) 構造体のアドレスを使用して、このような構造 体のリストに対して反復適用する dcmd usba_debug_buf -- -- USB デバッギング情報バッファを出力する dcmd usb_hcdi_cb -- -- 指定されたホストコントローラのコールバック構造体 (usb_hcdi_cb) のアドレスを使用して、このコールバック の要約情報を出力する dcmd usb_device -- -- 指定された usb_device 構造体のアドレスを使用して、要 約情報を出力する dcmd usb_pipe_handle -- -- 指 定 さ れ た USB パ イ プ ハ ン ド ル 構 造 体 (usb_pipe_handle_impl) のアドレスを使用して、このハン ドルの要約情報を出力する walk usb_hcdi_cb -- -- 指定された USB ホストコントローラの devinfo ノード のアドレスを使用して、このコントローラの usb_hcdi_cb_t 構造体のリストに対して反復適用する walk usba_list_entry -- -- 指定された usba_list_entry 構造体のアドレスを使用し て、このような構造体のチェインに対して反復適用する 3.6.2.5 ダンプ解析ツ--ル比較の考察 crash は、mdb に比べるとカーネルメモリアロケータ関連のコマンドが少ないが、内容 としてはかなり充実している。Crash ではカーネルメモリアロケータ関連のコマンド - 3-177 - を”kmem”コマンドのオプションで実装しているが、mdb はそれぞれ別のコマンドとしてサ ポートしている。好みが分かれるところだろうが、コマンドが少なく、オプションによる 指定が可能な crash の方が覚えやすいように感じた。 mdb はカーネルダンプの解析のみならず通常のプログラムのデバッガを兼ねているためコ マンド数は圧倒的に多く、Solaris 固有のデバッグ用構造体を編集するコマンドが多数見ら れる。特にメモリ管理に関してその傾向が強い。Alicia は、crash/lcrash の機能の繰り返し、 組み合わせ等を LDAS として記述することが可能であり、mdb コマンドの中で有効だと思 われるコマンドを Alicia コマンドとして追加していくことが可能である。今回の mdb コマ ンドの調査結果を元に Alicia の機能を更に高めていくことで、Linux のダンプ解析作業が より快適に、より迅速に実施できる環境を整備していきたい。 - 3-178 - 3.7 OSS 障害解析ツールの問題点と対策 現在、OSS 障害解析ツールは既存ツール自体の問題を含め、商用のものと比べて解析ツ ールが不足しているなど、様々な問題がある。 今回の障害解析ツール評価の結果、OSS 障害解析ツールの現状の問題点を次の表に示す。 対策については、既に対応が済んでいるものもあるが、現時点では、十分な対応ができて いないため、今後の課題としているものもある。課題の解決方法の一つとして、OSS コミ ュニティに提言することも考えられる。 図 3.7-1 項 番 1 分類 OSS 障害解析ツールの問題点 問題点 対策 sar コマンドの結果が欠落する 3.1.5.4 節の回避策参照 高負荷時に strace コマンドがトレース対象プ strace 出力を ramfs に出力する(改 特有の問題 ロセスの処理を遅延させてしまう 善策) 動作不良 strace strace 4.5.9 で、修正済み 高負荷時に 特有の問題 2 3 コ マ ン ド の --e signal=SIGXXX(XXX は任意)オ プションを使用すると、エラーが返 されてしまう 4 5 情報不足 情報不足 ダンプが取れても、その障害に至る システム・ログ、アプリケーション までの経緯が分からない のログをダンプと一緒に採取する ドキュメントが不足している(例: OSS 障害解析に必要なドキュメン /proc 下にどのような情報がどのよ ト整備、公開 うなフォーマットで格納されてい テナンスが今後の課題である 及び、継続的なメン るか) 6 情報不足 カーネルパニック時にコンソール シリアルコンソールを使用する に表示されるメッセージが保存さ れない 7 8 情報不足 情報不足 pthread_create のマニュアルに、 コミュニティへの改善提案が今後 ENOMEM の記述がない の課題である 異なるバージョン間での挙動の違 カーネルのバージョン間での動作 い(例えば、出力数値の意味が異な 違いの情報を収集、公開していくこ る等)が大きい とが重要であるが、今後の課題であ る - 3-179 - 4 付録 <crash/lcrash/mdb コマンド結果比較> crash crash の出力結果 lrcash ポインターへのショートカット crash> *page c02943c0 * struct page { next = 0xc0fae740, prev = 0xc0018fb0, inode = 0x0, offset = 0x3f000, next_hash = 0xc02d6310, count = { counter = 0x1 }, flags = 0x310, wait = 0xc02943d8, pprev_hash = 0x0, buffers = 0x0 } シェルへのエスケープおよびコマンドを実行する !comman crash> !ls bin etc lib mnt ossback prod tftpboot var d boot home lost+found mycomputer portal root tmp dev initrd misc opt proc sbin usr コマンド別名を設定する crash> alias alias ORIGIN ALIAS builtin man builtin ? builtin quit builtin sf builtin sn builtin hex builtin dec builtin g builtin px builtin pd builtin for builtin size builtin dmesg builtin last COMMAND help help q set scroll off set scroll on set radix 16 set radix 10 gdb p -x p -d foreach * log ps –l lcrash の出力結果 mdb mdb の出力結果 -- -- -- !comman d >!ls bin etc lib mnt ossback prod tftpboot var boot home lost+found mycomputer portal root tmp dev initrd misc opt proc sbin usr ::stack > ::stack vpanic(116f1d0, ff3eec00, 3, ff3efa80, 1f, ffbffb0c) kadmin+0x550(5, 1, 0, 300003f97a8, 5, 0) -- crash> alias kp kmem -p ORIGIN ALIAS COMMAND runtime kp kmem -p 16 進法のストリングをASCII に変換する crash> ascii 62696c2f7273752f ascii 62696c2f7273752f: /usr/lib バックトレースを表示する bt -- task_list に含まれる task の stack trace を表示する crash> bt PID: 0 TASK: c0322a60 CPU: 0 COMMAND: "swapper" #0 [c03b4fa4] smp_call_function_interrupt at c0118cda bt, デフォルトCPU のレジスタ情報を表示する >> trace ================================================================ STACK TRACE FOR TASK: 0xc5934000(krnl-1) - 4-1 - #1 [c03b4fac] call_function_interrupt at c02d4b9d EAX: 00000000 EBX: c03b4000 ECX: 00000000 EDX: 00000000 EBP: 004d7007 DS: 007b ESI: 00000000 ES: 007b EDI: c03eb120 CS: 0060 EIP: c01040ea ERR: fffffffb EFLAGS: 00000246 #2 [c03b4fe0] mwait_idle at c01040ea #3 [c03b4fe8] cpu_idle at c01040a0 crash> bt –a PID: 0 TASK: c0322a60 CPU: 0 COMMAND: "swapper" #0 [c03b4fa4] smp_call_function_interrupt at c0118cda #1 [c03b4fac] call_function_interrupt at c02d4b9d EAX: 00000000 EBX: c03b4000 ECX: 00000000 EDX: 00000000 EBP: 004d7007 DS: 007b ESI: 00000000 ES: 007b EDI: c03eb120 CS: 0060 EIP: c01040ea ERR: fffffffb EFLAGS: 00000246 #2 [c03b4fe0] mwait_idle at c01040ea #3 [c03b4fe8] cpu_idle at c01040a0 trace t strace rd 0 do_coprocessor_error [0xc010cbc0] 1 restore_i387_fxsave+36 [0xc0112bc4] 2 restore_i387+120 [0xc0112c98] 3 restore_sigcontext+270 [0xc010b1de] 4 sys_sigreturn+204 [0xc010b2cc] 5 no_timing+5 [0xc03b80d1] 6 LKST_ETYPE_SYSCALL_ENTRY_HEADER_hook+53 [0xc03b8036] ================================================================ >> trace -f ================================================================ STACK TRACE FOR TASK: 0xc5934000(krnl-1) 0 do_coprocessor_error [0xc010cbc0] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 PID: 0 TASK: f7f310b0 CPU: 1 COMMAND: "swapper" #0 [f7f0bf7c] smp_call_function_interrupt at c0118cda #1 [f7f0bf84] call_function_interrupt at c02d4b9d EAX: 00000000 EBX: f7f0b000 ECX: 00000000 EDX: 00000000 EBP: 00000000 DS: 007b ESI: 00000000 ES: 007b EDI: 00000000 CS: 0060 EIP: c01040ea ERR: fffffffb EFLAGS: 00000246 #2 [f7f0bfb8] mwait_idle at c01040ea #3 [f7f0bfc0] cpu_idle at c01040a0 PID: 0 TASK: f7f30b30 CPU: 2 COMMAND: "swapper" #0 [f7f0dcec] disk_dump at f893ea54 #1 [f7f0dcf0] printk at c0124c8f #2 [f7f0dcfc] freeze_other_cpus at f893e885 #3 [f7f0dd0c] start_disk_dump at f893e930 #4 [f7f0dd1c] try_crashdump at c0136eed #5 [f7f0dd24] die at c010603f #6 [f7f0dd58] LKST_ETYPE_OOPS_PGFAULT_HEADER_hook at c011d498 #7 [f7f0ddb4] vgacon_scroll at c01cbdd9 #8 [f7f0dde4] LKST_ETYPE_TIMER_MOD_HEADER_hook at c012c0ba #9 [f7f0de00] poke_blanked_console at c020a096 #10 [f7f0de04] vt_console_print at c0209428 #11 [f7f0de24] __call_console_drivers at c0124a2d #12 [f7f0de38] error_code at c02d4c88 EAX: 00000063 EBX: c035fc34 ECX: ee869000 EDX: f7f0df88 EBP: f7f0df88 DS: 007b ESI: 00000063 ES: 007b EDI: ee869000 CS: 0060 EIP: c020a974 ERR: ffffffff EFLAGS: 00010046 #13 [f7f0de74] sysrq_handle_crash at c020a974 #14 [f7f0de98] kbd_event at c02058b7 #15 [f7f0deb0] input_event at c026789e #16 [f7f0dedc] atkbd_interrupt at c026aa8a #17 [f7f0df28] i8042_interrupt at c0217291 #18 [f7f0df58] LKST_ETYPE_INT_HARDWARE_ENTRY_HEADER_hook at c0107a35 #19 [f7f0df84] common_interrupt at c02d4b3b EAX: 00000000 EBX: f7f0d000 ECX: 00000000 EDX: 00000000 EBP: 00000000 DS: 007b ESI: 00000000 ES: 007b EDI: 00000000 CS: 0060 EIP: c01040ea ERR: ffffff01 EFLAGS: 00000246 #20 [f7f0dfb8] mwait_idle at c01040ea #21 [f7f0dfc0] cpu_idle at c01040a0 1 restore_i387_fxsave+36 [0xc0112bc4] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 2 restore_i387+120 [0xc0112c98] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 3 restore_sigcontext+270 [0xc010b1de] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 4 sys_sigreturn+204 [0xc010b2cc] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 5 no_timing+5 [0xc03b80d1] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 6 LKST_ETYPE_SYSCALL_ENTRY_HEADER_hook+53 [0xc03b8036] RA=0x00000000, SP=0x00000000, FP=0x00000000, SIZE=0 ================================================================ >> rd CPU: 0 EIP: 0060:[<c03b81d7>] EFLAGS: 00000246 eax: 00000000 ebx: bfffb4d8 ecx: bfffb4d8 esi: bfffb4d8 edi: c5935fb0 ebp: bfffb480 ds: 0068 es: 0068 ss: 0068 PID: 0 TASK: f7f305b0 CPU: 3 COMMAND: "swapper" #0 [f7f0ef7c] smp_call_function_interrupt at c0118cda #1 [f7f0ef84] call_function_interrupt at c02d4b9d EAX: 00000000 EBX: f7f0e000 ECX: 00000000 EDX: 00000000 EBP: 00000000 DS: 007b ESI: 00000000 ES: 007b EDI: 00000000 CS: 0060 EIP: c01040ea ERR: fffffffb EFLAGS: 00000246 #2 [f7f0efb8] mwait_idle at c01040ea #3 [f7f0efc0] cpu_idle at c01040a0 - 4-2 - edx: c5934000 esp: c5935ec8 uadmin+0x104(5, 1, 0, 6d700000, 6d70, ffbffd91) syscall_trap32+0xa8(5, 1, 0, 6d700000, 6d70, ffbffd91) ::regs >::regs %g0 = 0x0000000000000000 %l0 = 0x00000000ff3ec0c0 %g1 = 0x000000000113e000 ttyinit+0x1a8 %l1 = 0x00000000ff3ec8bc %g2 = 0x000000000116f000 %l2 = 0x00000000ff3ec264 %g3 = 0x000000000140e000 kstat_data_type+0x70 %l3 = 0x00000000ff3ee4a4 %g4 = 0x00000000000006e0 %l4 = 0x00000000000217b4 %g5 = 0x0000000001449bf8 sysent32+0x6e0 %l5 = 0x0000000001000000 scb %g6 = 0x0000000000000000 %l6 = 0x0000000000000000 %g7 = 0x000003000333a2e0 %l7 = 0x0000000000010883 %o0 = 0x000000000116f1d0 %i0 = 0x000000000116f1d0 %o1 = 0x000002a1008658f8 %i1 = 0x00000000ff3eec00 %o2 = 0x00000000ff3ec204 %i2 = 0x0000000000000003 %o3 = 0x0000000000031344 %i3 = 0x00000000ff3efa80 %o4 = 0x00000000ff3c3050 %i4 = 0x000000000000001f %o5 = 0x00000000f0000000 %i5 = 0x00000000ffbffb0c %o6 = 0x000002a100864fc1 %i6 = 0x000002a100865071 %o7 = 0x000000000104c150 panic+0x1c %i7 = 0x000000000113e788 kadmin+0x550 %ccr = 0x44 xcc=nZvc icc=nZvc %fprs = 0x00 fef=0 du=0 dl=0 %asi = 0x00 %y = 0x0000000000000000 %pc = 0x0000000001037538 vpanic %npc = 0x000000000103753c vpanic+4 %sp = 0x000002a100864fc1 unbiased=0x000002a1008657c0 %fp = 0x000002a100865071 %tick = 0x0000000000000000 %tba = 0x0000000000000000 %tt = 0x0 %tl = 0x0 %pil = 0x0 %pstate = 0x016 cle=0 tle=0 mm=TSO red=0 pef=1 am=0 priv=1 ie=1 ag=0 %cwp = 0x05 %cansave = 0x00 %canrestore = 0x00 %otherwin = 0x00 %wstate = 0x00 %cleanwin = 0x00 crash> bt PID: 0 c03b4000: c03b4010: c03b4020: c03b4030: c03b4040: c03b4050: c03b4060: c03b4070: c03b4080: c03b4090: c03b40a0: c03b40b0: c03b40c0: c03b40d0: c03b40e0: c03b40f0: c03b4100: c03b4110: c03b4120: c03b4130: c03b4140: c03b4150: –r TASK: c0322a60 CPU: 0 COMMAND: "swapper" init_task default_exec_domain 00010008 00000000 00000000 00010000 ffffffff 00000000 init_thread_union 00000000 00000000 do_no_restart_syscall 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 crash> bt -t PID: 0 TASK: c0322a60 CPU: 0 COMMAND: "swapper" START: smp_call_function_interrupt at c0118cda [c03b4fac] call_function_interrupt at c02d4ba2 [c03b4fd8] mwait_idle at c01040ea [c03b4fe8] cpu_idle at c01040a2 [c03b4fec] start_kernel at c03b5784 [c03b4ffc] L6 at c0100211 crash> bt -e PID: 0 TASK: c0322a60 CPU: 0 KERNEL-MODE EXCEPTION FRAME AT EAX: 00000000 EBX: c03b4000 DS: 007b ESI: 00000000 CS: 0060 EIP: c01040ea COMMAND: "swapper" c03b4fb0: ECX: 00000000 EDX: 00000000 EBP: 004d7007 ES: 007b EDI: c03eb120 ERR: fffffffb EFLAGS: 00000246 crash> bt -E CPU 0 HARD IRQ STACK: (none found) CPU 1 HARD IRQ STACK: (none found) CPU 2 HARD IRQ STACK: (none found) CPU 3 HARD IRQ STACK: (none found) CPU 0 SOFT IRQ STACK: (none found) CPU 1 SOFT IRQ STACK: (none found) CPU 2 SOFT IRQ STACK: (none found) - 4-3 - CPU 3 SOFT IRQ STACK: (none found) crash> bt -f PID: 0 TASK: c0322a60 CPU: 0 COMMAND: "swapper" #0 [c03b4fa4] smp_call_function_interrupt at c0118cda [RA: c02d4ba2 SP: c03b4fa4 FP: c03b4fac SIZE: 12] c03b4fa4: c03b4000 00000000 c02d4ba2 #1 [c03b4fac] call_function_interrupt at c02d4b9d EAX: 00000000 EBX: c03b4000 ECX: 00000000 EDX: 00000000 EBP: 004d7007 DS: 007b ESI: 00000000 ES: 007b EDI: c03eb120 CS: 0060 EIP: c01040ea ERR: fffffffb EFLAGS: 00000246 [RA: c01040ea SP: c03b4fb0 FP: c03b4fe0 SIZE: 52] c03b4fb0: c03b4000 00000000 00000000 00000000 c03b4fc0: c03eb120 004d7007 00000000 c032007b c03b4fd0: 0000007b fffffffb c01040ea 00000060 c03b4fe0: 00000246 #2 [c03b4fe0] mwait_idle at c01040ea [RA: c01040a2 SP: c03b4fe4 FP: c03b4fe8 SIZE: 8] c03b4fe4: c03b4000 c01040a2 #3 [c03b4fe8] cpu_idle at c01040a0 [RA: 0 SP: c03b4ffc FP: c03b4ffc SIZE: 0] 16 進アドレスとそのページ番号に変更する crash> btop 512a000 btop 512a000: 512a -- -- -- ::devna mes ::prtco nf デバイスデータを表示する dev crash> dev CHRDEV NAME 1 mem 2 pty 3 ttyp 4 ttyS 5 cua 7 vcs 10 misc 13 input 29 fb 36 netlink 128 ptm 129 ptm 130 ptm 131 ptm 132 ptm 133 ptm 134 ptm 135 ptm 136 pts 137 pts 138 pts 139 pts crash> dev -i RESOURCE RANGE c0355060 0000-ffff c03542a0 0000-001f c03542bc 0020-003f c03542d8 0040-005f c03542f4 0060-006f c1543600 0070-007f c0354310 0080-008f c035432c 00a0-00bf OPERATIONS c03761e0 c0376240 c0376240 c0376240 c0376240 c03768a0 c03764e0 c8856600 c03af660 c03b0f80 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 c0376240 <memory_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <vcs_fops> <misc_fops> <input_fops> <fb_fops> <netlink_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> <tty_fops> >devnames NAME cn rootnex pseudo ip logindmux icmp fas hme eri pcf8584 max1617 clone sad mm iwscn wc conskbd consms tda8444 dump se log DN_HEAD 30000aeb250 30000295d08 3000028c1f0 30000871b58 3000328c950 30000871078 0 0 30000293400 30000292cc0 30000291978 30000871d28 30000870b08 30000aeb080 300008703c8 30000870768 30000870938 30000870598 300002917a8 3000328c210 30000290588 30000aea3d0 >::prtconf EVINFO NAME 30000295d08 SUNW,Sun-Blade-1000 30000295b38 packages (driver not attached) 30000295798 SUNW,builtin-drivers (driver not attached) 300002955c8 deblocker (driver not attached) 300002953f8 disk-label (driver not attached) 30000295228 terminal-emulator (driver not attached) 30000295058 obp-tftp (driver not attached) 30000294e88 dropins (driver not attached) NAME PCI IO dma1 pic1 timer keyboard rtc dma page reg pic2 - 4-4 - c0354348 c0354364 c1543800 c1543780 c15435c0 c15437c0 c03addbc c1543740 c1543580 c1532920 c153293c c15432c0 c1533920 c1531878 c1532c78 c7c14680 c15324cc c14f45c0 c15320cc c15436c0 c1543700 00c0-00df 00f0-00ff 0170-0177 01f0-01f7 02f8-02ff 0376-0376 03c0-03df 03f6-03f6 03f8-03ff 0400-043f 0440-045f 0cf8-0cff b000-cfff c800-c8ff dc00-dc1f dc00-dc1f de00-de1f de00-de1f ffa0-ffaf ffa0-ffa7 ffa8-ffaf dma2 fpu ide1 ide0 serial(auto) ide1 vga+ ide0 serial(auto) Intel Corp. 82371AB/EB/MB PIIX4 Intel Corp. 82371AB/EB/MB PIIX4 PCI conf1 PCI Bus #01 ATI Technologies Inc 3D Rage LT Intel Corp. 82557/8/9 [Ethernet e100 Intel Corp. 82371AB/EB/MB PIIX4 usb-uhci Intel Corp. 82371AB/EB/MB PIIX4 ide0 ide1 RESOURCE c035507c c079b000 c079b080 c03543b8 c03543fc c0354418 c03543e0 c079b180 c0354380 c035439c c079b200 c079b280 c1533958 c153185c c153345c bridge c1532c5c c7c14640 c153393c c1531894 c1531078 RANGE 00000000-ffffffff 00000000-0009f7ff 0009f800-0009ffff 000a0000-000bffff 000c0000-000c7fff 000cb800-000cbfff 000f0000-000fffff 00100000-07fdffff 00100000-002895e6 002895e7-003b5587 07fe0000-07ff7fff 07ff8000-07ffffff e5600000-e76fffff e6000000-e6ffffff e8000000-ebffffff NAME PCI mem System RAM reserved Video RAM area Video ROM Extension ROM System ROM System RAM Kernel code Kernel data ACPI Tables ACPI Non-volatile Storage PCI Bus #01 ATI Technologies Inc 3D Rage LT Pro AGP-133 Intel Corp. 440BX/ZX/DX - 82443BX/ZX/DX Host ef7ff000-ef7fffff ef7ff000-ef7fffff ef800000-ef8fffff ef8ff000-ef8fffff efc00000-efcfffff Intel Corp. 82557/8/9 [Ethernet Pro 100] e100 PCI Bus #01 ATI Technologies Inc 3D Rage LT Pro AGP-133 Cirrus Logic CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] Cirrus Logic CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] Intel Corp. 82557/8/9 [Ethernet Pro 100] e100 reserved c153105c efdff000-efdfffff 30000294cb8 kbd-translator (driver not attached) 30000294ae8 ufs-file-system (driver not attached) 30000295968 chosen (driver not attached) 30000294918 openprom (driver not attached) 30000294578 client-services (driver not attached) 30000294748 options, instance #0 300002943a8 aliases (driver not attached) 300002941d8 memory (driver not attached) 30000294008 virtual-memory (driver not attached) 30000293d10 SUNW,UltraSPARC-III, instance #0 30000293b40 memory-controller, instance #0 30000293970 pci108e,8001, instance #0 300002935d0 ebus, instance #0 30000293230 flashprom (driver not attached) 30000293060 bbc (driver not attached) 30000292e90 ebus-ppm, instance #0 30000292cc0 SUNW,bbc-i2c, instance #0 30000292920 i2c-at24c64, instance #0 30000292750 i2c-at24c64, instance #1 30000292580 i2c-at24c64, instance #2 300002923b0 i2c-at24c64, instance #3 300002921e0 i2c-at24c64, instance #4 30000292010 idprom (driver not attached) 30000292af0 SUNW,bbc-i2c, instance #1 30000291b48 i2c-at24c64, instance #5 30000291978 i2c-max1617, instance #0 300002917a8 i2c-tda8444, instance #0 300002915d8 i2c-scm001 (driver not attached) 30000291408 i2c-at24c64, instance #6 30000291238 i2c-bridge (driver not attached) 30000291d18 SUNW,bbc-beep, instance #0 30000291068 SUNW,CS4231 (driver not attached) 30000290e98 ds1287, instance #0 30000290cc8 gpio (driver not attached) 30000290af8 pmc (driver not attached) 30000290928 fdthree (driver not attached) 30000290758 ns87317-ecpp (driver not attached) 30000290588 se, instance #0 30000293400 pci108e,1101, instance #0 300002903b8 pciclass,0c0010, instance #0 300002901e8 pciclass,0c0310, instance #0 3000028dd20 usbif,class3, instance #4 3000028db50 usbif,class3, instance #2 30000290018 pci1000,f, instance #0 3000028d7b0 sd (driver not attached) 3000028d5e0 st (driver not attached) 30000aea940 sd, instance #0 (driver not attached) 30000aeab10 sd, instance #1 (driver not attached) 30000aeaeb0 sd, instance #2 (driver not attached) 30000aebb60 sd, instance #3 (driver not attached) 30000aebd30 sd, instance #4 (driver not attached) 30000870cd8 sd, instance #5 (driver not attached) 300019c9b68 sd, instance #6 300019c9998 sd, instance #7 (driver not attached) 300019c97c8 sd, instance #8 (driver not attached) 300019c95f8 sd, instance #9 (driver not attached) 300019c9428 sd, instance #10 (driver not attached) 300019c9258 sd, instance #11 (driver not attached) 300019c9088 sd, instance #12 (driver not attached) 300019c8eb8 sd, instance #13 (driver not attached) 300019c8ce8 sd, instance #14 (driver not attached) ACPI ACPI Pro AGP-133 Pro 100] USB IDE c1532c94 eff00000-efffffff c7c146c0 eff00000-efffffff c079b300 ffff0000-ffffffff crash> dev -p PCI_DEV BU:SL.FN CLASS: VENDOR-DEVICE c1533800 00:01.0 PCI bridge: Intel 440BX - 82443BX AGP c1533c00 00:07.0 ISA bridge: Intel 82371AB PIIX4 ISA c1532000 00:07.1 IDE interface: Intel 82371AB PIIX4 IDE c1532400 00:07.2 USB Controller: Intel 82371AB PIIX4 USB c1532800 00:07.3 Bridge: Intel 82371AB PIIX4 ACPI c1532c00 00:0a.0 Ethernet controller: Intel 82557 c1531000 00:0b.0 Multimedia audio controller: Cirrus Logic [PCI_DEVICE 6003] c1531800 01:00.0 VGA compatible controller: ATI [PCI_DEVICE 4c42] 逆アセンブルを行う - 4-5 - dis crash> dis 0xc0130095 0xc0130098 0xc013009c 0xc013009e 0xc01300a6 0xc01300aa 0xc01300ae 0xc01300b2 0xc01300b7 0xc01300b9 0xc01300bd 0xc01300c0 sys_signal <sys_signal>: <sys_signal+3>: <sys_signal+7>: <sys_signal+9>: <sys_signal+17>: <sys_signal+21>: <sys_signal+25>: <sys_signal+29>: <sys_signal+34>: <sys_signal+36>: <sys_signal+40>: <sys_signal+43>: crash> dis 0xc0138340 0xc0138341 0xc0138342 0xc0138343 0xc0138344 0xc0138347 0xc013834b 0xc013834f 0xc0138353 0xc0138357 0xc013835b 0xc013835f 0xc0138363 0xc0138367 0xc013836b 0xc013836f 0xc0138372 0xc0138374 je 0xc013837a 0xc013837d 0xc013837f je -r (do_no_page+65) <do_no_page>: push %ebp <do_no_page+1>: push %edi <do_no_page+2>: push %esi <do_no_page+3>: push %ebx <do_no_page+4>: sub $0x3c,%esp <do_no_page+7>: mov 0x50(%esp),%eax <do_no_page+11>: mov 0x58(%esp),%edx <do_no_page+15>: mov 0x54(%esp),%esi <do_no_page+19>: mov 0x60(%esp),%ebx <do_no_page+23>: mov %eax,0x38(%esp) <do_no_page+27>: mov 0x5c(%esp),%eax <do_no_page+31>: mov %edx,0x34(%esp) <do_no_page+35>: mov 0x64(%esp),%edx <do_no_page+39>: mov %eax,0x30(%esp) <do_no_page+43>: mov %edx,0x2c(%esp) <do_no_page+47>: mov 0x30(%esi),%edx <do_no_page+50>: test %edx,%edx <do_no_page+52>: 0xc0138741 <LKST_ETYPE_MEM_DO_NOPAGE_HEADER_hook+624> <do_no_page+58>: mov 0x8(%edx),%eax <do_no_page+61>: test %eax,%eax <do_no_page+63>: 0xc0138741 <LKST_ETYPE_MEM_DO_NOPAGE_HEADER_hook+624> sub mov mov movl mov mov lea call test cmove add ret $0x40,%esp 0x48(%esp),%edx %esp,%ecx $0xc0000000,0x24(%esp) 0x44(%esp),%eax %edx,0x20(%esp) 0x20(%esp),%edx 0xc012facd <do_sigaction> %eax,%eax (%esp),%eax $0x40,%esp 評価をおこなう crash> eval 128m eval hexadecimal: 8000000 (128MB) decimal: 134217728 octal: 1000000000 binary: 00001000000000000000000000000000 dis id print p pb,pd, po,px base >>dis 0xc010cbc0 0xc010cbc0 <do_coprocessor_error>: ::dis movb >> dis -f sys_signal 0xc012eb00 <sys_signal>: 0x8305 subl >> dis sys_signal 10 0xc012eb00 <sys_signal>: 0xc012eb03 <sys_signal+3>: 0xc012eb07 <sys_signal+7>: 0xc012eb0f <sys_signal+15>: 0xc012eb13 <sys_signal+19>: 0xc012eb17 <sys_signal+23>: 0xc012eb1b <sys_signal+27>: 0xc012eb1f <sys_signal+31>: 0xc012eb23 <sys_signal+35>: 0xc012eb27 <sys_signal+39>: subl movl movl movl leal movl leal movl movl movl $0x1,0xc03e7e20 $0x4c,%esp (3 bytes) $0x4c,%esp 0x54(%esp,1),%eax $0xc0000000,0x30(%esp,1) %eax,0x2c(%esp,1) 0xc(%esp,1),%eax %eax,0x8(%esp,1) 0x2c(%esp,1),%eax %eax,0x4(%esp,1) 0x50(%esp,1),%eax %eax,(%esp,1) >> print (*((struct task_struct *)0xc5c14000)->files.fd). f_flags & 0x8000 32768 ::eval >> base 10 -------------------------------------------------hex: 0xa decimal: 10 octal: 012 binary: 0b1010 -------------------------------------------------- 終了する exit q, q! ::quit コマンドセットの拡張 sial マクロをロードする - 4-6 - >::dis signal signal: signal+4: signal+8: signal+0xc: signal+0x10: signal+0x14: signal+0x18: signal+0x1c: signal+0x20: signal+0x24: signal+0x28: signal+0x2c: signal+0x30: signal+0x34: signal+0x38: signal+0x3c: signal+0x40: signal+0x44: signal+0x48: signal+0x4c: signal+0x50: signal+0x54: signal+0x58: signal+0x5c: signal+0x60: signal+0x64: signal+0x68: signal+0x6c: signal+0x70: signal+0x74: signal+0x78: signal+0x7c: signal+0x80: signal+0x84: signal+0x88: signal+0x8c: signal+0x90: signal+0x94: signal+0x98: signal+0x9c: signal+0xa0: signal+0xa4: signal+0xa8: save sethi add call mov sethi add call mov sra cmp be,pn nop call mov orcc be,pn nop call mov ldx cmp be,pn nop ldx call nop sra clr call mov call ldx ldx cmp bne,a,pt ldx call restore call mov call restore %sp, -0xb0, %sp %hi(0x149e000), %l4 %l4, 0x168, %l3 -0x9527c <mutex_enter> %l3, %o0 %hi(0x1457800), %g2 %g2, 0x2e0, %l5 -0x9528c <mutex_enter> %l5, %o0 %i0, 0, %l0 %l0, 0 %icc,+0x70 <signal+0x9c> -0x8d4 <pid_lookup> %l0, %o0 %g0, %o0, %l0 %xcc,+0x5c <signal+0x9c> -0x95238 <mutex_exit> %l5, %o0 [%l0 + 8], %l0 %l0, 0 %xcc,+0x3c <signal+0x94> [%l0 + 0x10], %o0 -0x952d4 <mutex_enter> %i1, 0, %o2 %o1 +0x25ebc %l0, %o0 -0x9526c [%l0 + 0x10], [%l0 + 0x98], %l0, 0 %xcc,-0x28 [%l0 + 0x10], -0x95284 %g0, %l3, %o0 -0x9528c %l5, %o0 -0x95294 %g0, %l3, %o0 <sigtoproc> <mutex_exit> %o0 %l0 <signal+0x64> %o0 <mutex_exit> <mutex_exit> <mutex_exit> extend crash> extend extlib1.so extlib2.so ./extlib1.so: shared object loaded ./extlib2.so: shared object loaded オープン・ファイルを表示する crash> files files PID: 895 TASK: c5934000 CPU: 0 ROOT: / CWD: /opt/es7000/bin FD FILE DENTRY INODE 0 c6542480 c68ffa80 c60e0280 1 c6542480 c68ffa80 c60e0280 2 c6542480 c68ffa80 c60e0280 load COMMAND: "krnl-1" TYPE CHR CHR CHR ::load $<< -- -- -- -- PATH /dev/pts/0 /dev/pts/0 /dev/pts/0 システムのマルチタスクへのコマンドデータの表示を指示する foreach crash> foreach bt PID: 0 TASK: c0494000 CPU: 0 COMMAND: "swapper" #0 [c0495ec0] LKST_ETYPE_PROCESS_CONTEXTSWITCH_HEADER_hook at c012d782 #1 [c0495ec4] scheduler_tick at c01297ac #2 [c0495f24] smp_apic_timer_interrupt at c012176b #3 [c0495f78] cpu_idle at c0109309 PID: 0 (active) TASK: c8704000 CPU: 1 COMMAND: "swapper" PID: 0 (active) TASK: c8500000 CPU: 2 COMMAND: "swapper" PID: 0 (active) TASK: c6c66000 CPU: 3 COMMAND: "swapper" PID: 1 TASK: c8706000 CPU: 1 COMMAND: "init" bt: cannot resolve stack trace: #0 [c8707e00] LKST_ETYPE_PROCESS_CONTEXTSWITCH_HEADER_hook at c012d782 bt: text symbols on stack: [c8707e40] schedule at c0129b24 [c8707e64] __put_task_struct at c012de8b [c8707eb8] schedule_timeout at c0143045 [c8707ec4] __pollwait at c019faf1 [c8707ed8] process_timeout at c0142fd0 [c8707ef0] do_select at c019fdcb [c8707f3c] dput at c01a4e70 [c8707f60] sys_select at c01a031e [c8707fa8] sys_fstat64 at c0190bd9 [c8707fb4] no_timing at c04960d1 [c8707fc0] LKST_ETYPE_SYSCALL_ENTRY_HEADER_hook at c0496036 bt: possible exception frame: USER-MODE EXCEPTION FRAME AT c8707fc4: EAX: 0000008e EBX: 0000000b ECX: bfffcd50 EDX: 00000000 DS: 002b ESI: 00000000 ES: 002b EDI: bfffcc88 SS: 002b ESP: bfffcc50 EBP: bfffcf68 CS: 0023 EIP: b7577308 ERR: 0000008e EFLAGS: 00000246 PID: 2 TASK: c6c64000 CPU: 0 COMMAND: "migration/0" #0 [c6c65eb0] LKST_ETYPE_PROCESS_CONTEXTSWITCH_HEADER_hook at c012d782 #1 [c6c65ef0] schedule at c0129b1f #2 [c6c65f68] migration_task at c012d398 #3 [c6c65ff0] kernel_thread_helper at c01097fb PID: 3 TASK: f7fa6000 CPU: 1 COMMAND: "migration/1" #0 [f7fa7eb0] LKST_ETYPE_PROCESS_CONTEXTSWITCH_HEADER_hook at c012d782 #1 [f7fa7ef0] schedule at c0129b1f #2 [f7fa7f68] migration_task at c012d398 #3 [f7fa7ff0] kernel_thread_helper at c01097fb - 4-7 - PID: 4 TASK: f7fa4000 CPU: 2 COMMAND: "migration/2" #0 [f7fa5eb0] LKST_ETYPE_PROCESS_CONTEXTSWITCH_HEADER_hook at c012d782 #1 [f7fa5ef0] schedule at c0129b1f #2 [f7fa5f68] migration_task at c012d398 #3 [f7fa5ff0] kernel_thread_helper at c01097fb 指定されたファイルのユーザを表示する crash> fuser /usr/lib/libkfm.so.2.0.0 fuser PID TASK COMM USAGE 779 c5e82000 "kwm" mmap 808 c5a8e000 "krootwm" mmap 806 c5b42000 "kfm" mmap 809 c5dde000 "kpanel" mmap -- -- -- -- gdb コマンドを実行する gdb 使用可能なコマンドの一覧を表示する lcrash のバージョン情報を表示する help crash> help * alias ascii bt btop dev dis eval exit extend files foreach fuser gdb help irq kmem list log mach mod mount net p ps pte ptob ptov rd repeat runq search set sig struct swap sym sys task timer union vm vtop waitq whatis wr q help ? version crash version: 3.8-5 gdb version: 6.1 For help on any command above, enter "help <command>". For help on input options, enter "help input". For help on output options, enter "help output". >> help ? addtypes base bt defcpu deftask dis dt dump findsym fsym h help history id ::dcmds info ldcmds load main md mktrace mmap module mt namelist nmlist od offset p page pb pd po print ps px q q! quit rd report savedump set sizeof stat strace symbol symtab t task trace unload version vi vtop walk whatis >> version lcrash 0.9.2 (xlcrash) build at May 13 2004 23:41:53 Lcrash is free software. It is covered by the GNU General Public License. You are welcome to change it and/or distribute copies of it under certain conditions. Type "help -C" to see the conditions. Absolutely no warranty is given for Lcrash. Type "help -W" for warranty details. IRQ を表示する irq crash> irq IRQ: 0 STATUS: 0 HANDLER: c03faae0 typename: startup: shutdown: enable: disable: ack: end: set_affinity: ACTION: c03f9d48 handler: flags: mask: name: dev_id: next: DEPTH: 0 -- -- <ioapic_edge_irq_type> "IO-APIC-edge" <startup_edge_ioapic_irq> <disable_edge_ioapic_irq> <unmask_IO_APIC_irq> <disable_edge_ioapic_irq> <ack_edge_ioapic_irq> <end_edge_ioapic_irq> <set_ioapic_affinity> <irq0> c01151a0 <timer_interrupt> 20000000 (SA_INTERRUPT) 0 c032db68 "timer" 0 0 c032d13e c0122f40 c0122f30 c0122430 c0122f30 c0123090 c01230c0 c01232c0 - 4-8 - $< $<< $> $? $C $G $P $Q $V $W $X $Y $b $c $d $e $f $g $i - replace input with macro file source macro file log session to a file print status and registers print stack backtrace enable/disable C++ demangling support set debugger prompt string quit debugger get/set disassembly mode re-open target in write mode print floating point registers print floating point registers list traced software events print stack backtrace get/set default output radix print listing of global symbols print listing of source files get/set C++ demangling options print signals that are ignored IRQ: 1 STATUS: 0 HANDLER: c03faae0 typename: startup: shutdown: enable: disable: ack: end: set_affinity: ACTION: c86fdd80 handler: flags: mask: name: dev_id: next: DEPTH: 0 IRQ: 2 STATUS: 0 HANDLER: c03f9760 typename: startup: shutdown: enable: disable: ack: end: set_affinity: ACTION: c03f979c handler: flags: mask: name: dev_id: next: DEPTH: 0 c032d13e c0122f40 c0122f30 c0122430 c0122f30 c0123090 c01230c0 c01232c0 <ioapic_edge_irq_type> "IO-APIC-edge" <startup_edge_ioapic_irq> <disable_edge_ioapic_irq> <unmask_IO_APIC_irq> <disable_edge_ioapic_irq> <ack_edge_ioapic_irq> <end_edge_ioapic_irq> <set_ioapic_affinity> c02078e0 <keyboard_interrupt> 0 0 c032b4a1 "keyboard" 0 0 c032b47e c0112d20 c0112d40 c0112e80 c0112d40 c0112d40 c0112d00 0 <i8259A_irq_type> "XT-PIC" <startup_8259A_irq> <disable_8259A_irq> <enable_8259A_irq> <disable_8259A_irq> <disable_8259A_irq> <end_8259A_irq> <irq2> c010e390 <no_action> 0 0 c032b489 "cascade" 0 0 IRQ: 3 STATUS: 26 (IRQ_DISABLED|IRQ_PENDING|IRQ_WAITING) HANDLER: c03faae0 <ioapic_edge_irq_type> typename: c032d13e "IO-APIC-edge" startup: c0122f40 <startup_edge_ioapic_irq> shutdown: c0122f30 <disable_edge_ioapic_irq> enable: c0122430 <unmask_IO_APIC_irq> disable: c0122f30 <disable_edge_ioapic_irq> ack: c0123090 <ack_edge_ioapic_irq> end: c01230c0 <end_edge_ioapic_irq> set_affinity: c01232c0 <set_ioapic_affinity> ACTION: (none) DEPTH: 0 カーネルメモリ情報の表示 kmem crash> kmem –f NODE 0 ZONE NAME SIZE FREE MEM_MAP START_PADDR START_MAPNR 0 DMA 4096 2678 c100002c 0 0 AREA SIZE FREE_AREA_STRUCT BLOCKS PAGES 0 4k c0449d58 0 0 1 8k c0449d64 1 2 -::kmalo g ::kmast - 4-9 - > ::kmalog slab T-0.000000000 addr=301f6d26000 kmem_magazine_3 kmem_slab_create+0x278 kmem_slab_alloc+0x44 kmem_cache_alloc+0x154 kmem_cache_free+0xfc ufs_idle_some+0x164 ufs_thread_idle+0x1b4 2 3 4 5 6 7 8 9 10 16k 32k 64k 128k 256k 512k 1024k 2048k 4096k c0449d70 c0449d7c c0449d88 c0449d94 c0449da0 c0449dac c0449db8 c0449dc4 c0449dd0 1 0 1 1 1 0 0 1 2 4 0 16 32 64 0 0 512 2048 at ::kmaus ers ::kmem_ cache ::kmem_ ZONE NAME SIZE FREE MEM_MAP START_PADDR START_MAPNR 1 Normal 225280 2957 c103c02c 1000000 4096 AREA SIZE FREE_AREA_STRUCT BLOCKS PAGES 0 4k c044b058 1357 1357 1 8k c044b064 150 300 2 16k c044b070 7 28 3 32k c044b07c 1 8 4 64k c044b088 3 48 5 128k c044b094 0 0 6 256k c044b0a0 1 64 7 512k c044b0ac 1 128 8 1024k c044b0b8 0 0 9 2048k c044b0c4 0 0 10 4096k c044b0d0 1 1024 log ::kmem_ verify T-0.002343800 addr=301f982c000 kmem_magazine_3 kmem_slab_create+0x278 kmem_slab_alloc+0x44 kmem_cache_alloc+0x154 kmem_cache_free+0xfc ufs_idle_some+0x164 ufs_thread_idle+0x1b4 T-0.004701200 addr=301f982a000 kmem_magazine_3 kmem_slab_create+0x278 kmem_slab_alloc+0x44 kmem_cache_alloc+0x154 kmem_cache_free+0xfc ufs_idle_some+0x164 ufs_thread_idle+0x1b4 nr_free_pages: 6704 (verified) >::kmastat cache name ------------------------kmem_magazine_1 kmem_magazine_3 kmem_magazine_7 kmem_magazine_15 kmem_magazine_31 kmem_magazine_47 kmem_magazine_63 kmem_magazine_95 kmem_magazine_143 kmem_slab_cache kmem_bufctl_cache kmem_bufctl_audit_cache kmem_va_8192 kmem_va_16384 kmem_va_24576 kmem_va_32768 kmem_va_40960 kmem_va_49152 kmem_va_57344 kmem_va_65536 >kmem –F NODE 0 ZONE NAME 0 DMA AREA SIZE 0 4k AREA SIZE 1 8k c101655c AREA SIZE 2 16k c101646c AREA SIZE 3 32k AREA SIZE 4 64k c1000b6c AREA SIZE 5 128k c1001e2c AREA SIZE > ::kmem_cache ADDR 0000030000008008 0000030000008248 0000030000008488 00000300000086c8 0000030000008908 0000030000008b48 0000030000008d88 0000030000008fc8 0000030000009208 0000030000009448 0000030000009688 00000300000098c8 0000030000009b08 000003000000a008 000003000000a248 000003000000a488 000003000000a6c8 000003000000a908 000003000000ab48 000003000000ad88 ZONE NAME SIZE FREE MEM_MAP START_PADDR START_MAPNR 2 HighMem 1376256 1069 c1d2002c 38000000 229376 AREA SIZE FREE_AREA_STRUCT BLOCKS PAGES 0 4k c044c358 7 7 1 8k c044c364 3 6 2 16k c044c370 0 0 3 32k c044c37c 96 768 4 64k c044c388 4 64 5 128k c044c394 1 32 6 256k c044c3a0 1 64 7 512k c044c3ac 1 128 8 1024k c044c3b8 0 0 9 2048k c044c3c4 0 0 10 4096k c044c3d0 0 0 SIZE FREE MEM_MAP START_PADDR START_MAPNR 4096 2678 c100002c 0 0 FREE_AREA_STRUCT c0449d58 FREE_AREA_STRUCT c0449d64 FREE_AREA_STRUCT c0449d70 FREE_AREA_STRUCT c0449d7c FREE_AREA_STRUCT c0449d88 FREE_AREA_STRUCT c0449d94 FREE_AREA_STRUCT - 4-10 - buf buf buf memory alloc alloc size in use total in use succeed fail ------ ------ ------ --------- --------- ----16 1248 1524 24576 1248 0 32 4113 4318 139264 4113 0 64 2166 2286 147456 2166 0 128 1695 1701 221184 1695 0 256 0 0 0 0 0 384 0 0 0 0 0 512 0 0 0 0 0 768 0 0 0 0 0 1152 0 0 0 0 0 56 2430 2465 139264 2430 0 24 10830 10848 262144 10830 0 128 0 0 0 0 0 8192 5609 5632 46137344 5609 0 16384 17 32 524288 17 0 24576 12 20 524288 12 0 32768 0 0 0 0 0 40960 0 0 0 0 0 49152 0 0 0 0 0 57344 0 0 0 0 0 65536 0 0 0 0 0 NAME kmem_magazine_1 kmem_magazine_3 kmem_magazine_7 kmem_magazine_15 kmem_magazine_31 kmem_magazine_47 kmem_magazine_63 kmem_magazine_95 kmem_magazine_143 kmem_slab_cache kmem_bufctl_cache kmem_bufctl_audit_cache kmem_va_8192 kmem_va_16384 kmem_va_24576 kmem_va_32768 kmem_va_40960 kmem_va_49152 kmem_va_57344 kmem_va_65536 FLAG 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0200 0200 0200 0200 0200 0200 0200 0200 CFLAG BUFSIZE BUFTOTL 080000 16 1524 080000 32 4318 080000 64 2286 080000 128 1701 080000 256 0 080000 384 0 080000 512 0 080000 768 0 080000 1152 0 080000 56 2465 080000 24 10848 080000 128 0 110000 8192 5632 110000 16384 32 110000 24576 20 110000 32768 0 110000 40960 0 110000 49152 0 110000 57344 0 0 110000 65536 6 256k c1000f2c AREA SIZE 7 512k AREA SIZE 8 1024k AREA SIZE 9 2048k c101682c AREA SIZE 10 4096k c102d02c c101e02c c0449da0 000003000000afc8 kmem_alloc_8 000003000000b208 kmem_alloc_16 FREE_AREA_STRUCT c0449dac FREE_AREA_STRUCT c0449db8 FREE_AREA_STRUCT c0449dc4 > ::kmem_verify Cache Name kmem_alloc_8 kmem_alloc_16 kmem_alloc_24 kmem_alloc_32 kmem_alloc_40 kmem_alloc_48 FREE_AREA_STRUCT c0449dd0 ZONE NAME SIZE FREE MEM_MAP START_PADDR START_MAPNR 1 Normal 225280 2976 c103c02c 1000000 4096 AREA SIZE FREE_AREA_STRUCT 0 4k c044b058 c1999854 c1a45550 c1b1a55c c15e8a70 c125a8f4 c1aa2688 c182322c >kmem –p PAGE c100002c c1000068 c10000a4 c10000e0 c100011c c1000158 c1000194 c10001d0 c100020c c1000248 c1000284 c10002c0 c10002fc c1000338 c1000374 c10003b0 c10003ec c1000428 c1000464 c10004a0 c10004dc c1000518 PHYSICAL 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 a000 b000 c000 d000 e000 f000 10000 11000 12000 13000 14000 15000 MAPPING 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 INDEX CNT 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FLAGS 8000 8000 8000 8000 8000 8000 8000 8000 8000 8000 8000 8000 0 0 0 0 0 0 0 0 0 0 crash> kmem –C page_hash_table[0] c45070e0 page_hash_table[1] c45070a4 page_hash_table[2] c3d71b64 c4507068 page_hash_table[3] c4036b9c c450702c page_hash_table[4] c4517670 - 4-11 - 0000 200000 0000 200000 8 16 6102 3048 Addr Cache Integrity 70039428 clean 700396a8 clean 70039928 1 corrupt buffer 70039ba8 clean 7003a028 clean 7003a2a8 clean page_hash_table[5] c4517634 page_hash_table[6] c45175f8 page_hash_table[7] c45175bc page_hash_table[8] c4517580 page_hash_table[9] c4517544 page_hash_table[10] crash> kmem -i PAGES TOTAL MEM 1547863 FREE 6036 USED 1541827 SHARED 769436 BUFFERS 71882 CACHED 1428557 SLAB 31825 TOTAL 5.9 GB 23.6 MB 5.9 GB 2.9 GB 280.8 MB 5.4 GB 124.3 MB PERCENTAGE ---0% of TOTAL MEM 99% of TOTAL MEM 49% of TOTAL MEM 4% of TOTAL MEM 92% of TOTAL MEM 2% of TOTAL MEM TOTAL HIGH 1343440 FREE HIGH 374 TOTAL LOW 204423 FREE LOW 5662 5.1 1.5 798.5 22.1 86% 0% 13% 2% TOTAL SWAP 1536213 SWAP USED 0 SWAP FREE 1536213 crash>kmem –s ACHE NAME c0448880 kmem_cache dc76cecc ip_fib_hash f67c4afc urb_priv f67c4bf0 ext3_xattr f67c4ce4 journal_head f67c4dd8 revoke_table f67c4ecc revoke_record c87aedd8 clip_arp_cache c87aeecc ip_mrt_cache c874f080 tcp_tw_bucket c874f174 tcp_bind_bucket c874f268 tcp_open_request c874f35c inet_peer_cache c874f450 secpath_cache c874f544 xfrm_dst_cache c874f638 ip_dst_cache c874f72c arp_cache c874f820 flow_cache c874f914 blkdev_requests c874fa08 kioctx c874fafc kiocb c874fbf0 dnotify_cache GB MB MB MB of of of of TOTAL TOTAL TOTAL TOTAL MEM HIGH MEM LOW 5.9 GB ---0 0% of TOTAL SWAP 5.9 GB 100% of TOTAL SWAP OBJSIZE ALLOCATED 244 72 32 11 64 0 44 0 48 29 12 3 32 0 256 0 128 0 128 0 32 18 128 0 64 0 128 0 256 0 256 19 256 2 128 0 128 12288 128 0 128 0 20 0 crash>kmem –S CACHE NAME OBJSIZE ALLOCATED c0448880 kmem_cache 244 72 SLAB MEMORY TOTAL ALLOCATED FREE dc76c000 dc76c080 16 1 15 FREE / [ALLOCATED] dc76c080 (cpu 0 cache) dc76c174 (cpu 0 cache) TOTAL SLABS SSIZE 112 7 4k 336 3 4k 0 0 4k 0 0 4k 462 6 4k 500 2 4k 0 0 4k 0 0 4k 0 0 4k 0 0 4k 560 5 4k 0 0 4k 0 0 4k 0 0 4k 0 0 4k 150 10 4k 15 1 4k 0 0 4k 12840 428 4k 0 0 4k 0 0 4k 0 0 4k TOTAL SLABS SSIZE 112 7 4k - 4-12 - dc76c268 (cpu 0 dc76c35c (cpu 0 dc76c450 (cpu 0 dc76c544 (cpu 0 dc76c638 (cpu 0 dc76c72c (cpu 0 dc76c820 (cpu 0 dc76c914 (cpu 0 dc76ca08 (cpu 0 dc76cafc (cpu 0 dc76cbf0 (cpu 0 dc76cce4 (cpu 0 dc76cdd8 (cpu 0 [dc76cecc] SLAB MEMORY f67c4000 f67c4080 FREE / [ALLOCATED] f67c4080 (cpu 3 f67c4174 (cpu 3 f67c4268 (cpu 3 f67c435c (cpu 3 f67c4450 (cpu 3 f67c4544 (cpu 3 f67c4638 (cpu 3 f67c472c (cpu 3 f67c4820 (cpu 3 f67c4914 (cpu 3 f67c4a08 (cpu 3 [f67c4afc] [f67c4bf0] [f67c4ce4] [f67c4dd8] [f67c4ecc] cache) cache) cache) cache) cache) cache) cache) cache) cache) cache) cache) cache) cache) TOTAL ALLOCATED FREE 16 5 11 cache) cache) cache) cache) cache) cache) cache) cache) cache) cache) cache) crash> kmem –v VM_STRUCT ADDRESS c86fde40 f8800000 c87909c0 f880d000 c8790780 f882d000 f688bf40 f882f000 f688bec0 f8834000 c86cff40 f8836000 c86cfec0 f8843000 c86cfe80 f8845000 c86cfd80 f8847000 c86cff00 f8849000 c86cfcc0 f8857000 f67c7f40 f8859000 f67c7ec0 f886a000 f67c7f00 f886c000 f67c7e40 f8885000 c86cf6c0 f8887000 c86cf640 f889f000 f67c7e80 f88a1000 f67c7d00 f88aa000 f67c7d40 f88ac000 f67c7a40 f88af000 f67c7a80 f88b1000 - RANGE SIZE f880d000 53248 f882d000 131072 f882f000 8192 f8834000 20480 f8836000 8192 f8843000 53248 f8845000 8192 f8847000 8192 f8849000 8192 f8857000 57344 f8859000 8192 f886a000 69632 f886c000 8192 f8885000 102400 f8887000 8192 f889f000 98304 f88a1000 8192 f88aa000 36864 f88ac000 8192 f88af000 12288 f88b1000 8192 f88b8000 28672 crash >kmem –n ODE SIZE PGLIST_DATA 0 1605632 c0448b80 BOOTMEM_DATA c0577344 NODE_ZONES c0448b80 c0449e80 c044b180 - 4-13 - MEM_MAP START_PADDR START_MAPNR c100002c 0 0 ZONE 0 1 2 NAME DMA Normal HighMem SIZE MEM_MAP START_PADDR START_MAPNR 4096 c100002c 0 0 225280 c103c02c 1000000 4096 1376256 c1d2002c 38000000 229376 リンクしたリストを表示する カーネル構造体またはメモリブロックのリンクされたリストをたどる crash> list task_struct.p_pptr c169a000 >> walk -l list walk c169a000 NUM NAME SIZE c0440000 =================================== c50d0000 0 mm_struct 292 c0562000 1 page 56 c0d28000 2 task_struct 1792 c7894000 3 vm_area_struct 68 c6a98000 4 module 96 c009a000 =================================== c0252000 >> walk list_head next 0xc03738c4 -h n -t STRUCT ADDR PREV LISTHEAD NEXT ============================================ 0 0xc6d80d08 0xc03738c4 0xc6d22108 0xc6d22108 0xc03738c4 0xc6d22108 0xc13e3a88 0xc13e3a88 0xc6d22108 0xc13e3a88 0xc6df0b88 0xc6df0b88 0xc13e3a88 0xc6df0b88 0xc7fccc88 0xc7fccc88 0xc6df0b88 0xc7fccc88 0xc6d21788 0xc6d21788 0xc7fccc88 0xc6d21788 0xc6d33088 0xc6d33088 0xc6d21788 0xc6d33088 0xc6d33288 0xc6d33288 0xc6d33088 0xc6d33288 0xc6d21d88 0xc6d21d88 0xc6d33288 0xc6d21d88 0xc6d21b88 0xc6d21b88 0xc6d21d88 0xc6d21b88 0xc6d21988 0xc6d21988 0xc6d21b88 0xc6d21988 0xc7fcc288 0xc7fcc288 0xc6d21988 0xc7fcc288 0xc6d21588 0xc6d21588 0xc7fcc288 0xc6d21588 0xc6d21388 0xc6d21388 0xc6d21588 0xc6d21388 0xc6d21188 0xc6d21188 0xc6d21388 0xc6d21188 0xc7fcc688 0xc7fcc688 0xc6d21188 0xc7fcc688 0xc7fcca88 0xc7fcca88 0xc7fcc688 0xc7fcca88 0xc7fcc888 0xc7fcc888 0xc7fcca88 0xc7fcc888 0xc7fcc488 0xc7fcc488 0xc7fcc888 0xc7fcc488 0xc12b6d08 0xc12b6d08 0xc7fcc488 0xc12b6d08 0xc6dd6b08 0xc6dd6b08 0xc12b6d08 0xc6dd6b08 0xc6dd6508 0xc6dd6508 0xc6dd6b08 0xc6dd6508 0xc6d69288 0xc6d69288 0xc6dd6508 0xc6d69288 0xc6df0d88 0xc6df0d88 0xc6d69288 0xc6df0d88 0xc6df0188 0xc6df0188 0xc6df0d88 0xc6df0188 0xc6d80d08 0xc6d80d08 0xc6df0188 0xc6d80d08 0xc03738c4 ============================================ walk ダンプ・システム・メッセージ・バッファーを表示する log Linux version 2.4.21-9.30AX ([email protected]) (gcc version 3.2.3 20030502 ( Asianux 1.0 3.2.3-35AX)) #1 Thu May 27 00:03:41 EDT 2004 BIOS-provided physical RAM map: BIOS-e820: 0000000000000000 - 000000000009f800 (usable) BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved) BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved) BIOS-e820: 0000000000100000 - 0000000007fe0000 (usable) BIOS-e820: 0000000007fe0000 - 0000000007ff8000 (ACPI data) BIOS-e820: 0000000007ff8000 - 0000000008000000 (ACPI NVS) BIOS-e820: 00000000ffff0000 - 0000000100000000 (reserved) -- -- - 4-14 - 0MB HIGHMEM available. 127MB LOWMEM available. On node 0 totalpages: 32736 zone(0): 4096 pages. zone(1): 28640 pages. zone(2): 0 pages. Kernel command line: ro root=LABEL=/ Initializing CPU#0 Detected 451.031 MHz processor. Console: colour VGA+ 80x25 Calibrating delay loop... 897.84 BogoMIPS Memory: 120128k/130944k available (1573k kernel code, 9408k reserved, 1199k data , 164k init, 0k highmem) マシン固有のデータを表示する crash> mach mach MACHINE TYPE: MEMORY SIZE: CPUS: PROCESSOR SPEED: HZ: PAGE SIZE: L1 CACHE SIZE: KERNEL VIRTUAL BASE: KERNEL VMALLOC BASE: KERNEL STACK SIZE: i686 128 MB 1 451 Mhz 100 4096 128 c0000000 c8800000 8192 -- ::cpuin fo > ::cpuinfo ID ADDR FLG NRUN BSPL PRI RNRN KRNRN SWITCH THREAD PROC 0 000014315b0 1b 0 0 0 no no t-0 3000333a2e0 reboot モジュール情報およびシンボルとデバッグするデータのロードをおこなう ロードしたモジュールまたはモジュールシンボルを表示する mod rash> mod MODULE c880d000 c881d000 c8835000 c884b000 c8855000 c885a000 c8863000 c8868000 c8891000 c88aa000 c88c5000 c88cf000 c88e2000 NAME SIZE OBJECT FILE jbd 50572 (not loaded) [CONFIG_KALLSYMS] ext3 85704 (not loaded) [CONFIG_KALLSYMS] usbcore 77152 (not loaded) [CONFIG_KALLSYMS] usb-uhci 25836 (not loaded) [CONFIG_KALLSYMS] input 5856 (not loaded) [CONFIG_KALLSYMS] hid 22084 (not loaded) [CONFIG_KALLSYMS] mousedev 5492 (not loaded) [CONFIG_KALLSYMS] keybdev 2976 (not loaded) [CONFIG_KALLSYMS] microcode 5816 (not loaded) [CONFIG_KALLSYMS] scsi_mod 103336 (not loaded) [CONFIG_KALLSYMS] sg 36140 (not loaded) [CONFIG_KALLSYMS] floppy 56688 (not loaded) [CONFIG_KALLSYMS] e100 56880 (not loaded) [CONFIG_KALLSYMS] crash> mod -S mod: NOTE: /lib/jbd.o: installed from initrd image MODULE NAME SIZE OBJECT FILE c880d000 jbd 50572 /lib/modules/2.4.21-9.30AX/kernel/fs/jbd/jbd.o mod: NOTE: /lib/ext3.o: installed from initrd image c881d000 ext3 85704 /lib/modules/2.4.21-9.30AX/kernel/fs/ext3/ext3.o c8835000 usbcore 77152 /lib/modules/2.4.21-9.30AX/kernel/drivers/usb/usbcore.o c884b000 usb-uhci 25836 /lib/modules/2.4.21-9.30AX/kernel/drivers/usb/host/usb-uhci.o c8855000 input 5856 /lib/modules/2.4.21-9.30AX/kernel/drivers/input/input.o c885a000 hid 22084 /lib/modules/2.4.21-9.30AX/kernel/drivers/usb/hid.o c8863000 mousedev 5492 /lib/modules/2.4.21-9.30AX/kernel/drivers/input/mousedev.o c8868000 keybdev 2976 /lib/modules/2.4.21-9.30AX/kernel/drivers/input/keybdev.o c8891000 microcode 5816 /lib/modules/2.4.21-9.30AX/kernel/arch/i386/kernel/microcode.o c88aa000 scsi_mod 103336 /lib/modules/2.4.21-9.30AX/kernel/drivers/scsi/scsi_mod.o c88c5000 sg 36140 /lib/modules/2.4.21-9.30AX/kernel/drivers/scsi/sg.o module >> module ADDR SIZE USED NAME REFS ==================================================================== ======= 0xc88e2000 56880 1 e100 [] 0xc88cf000 56688 0 floppy [] 0xc88c5000 36140 0 sg [] 0xc88aa000 103336 1 scsi_mod [sg] 0xc8891000 5816 0 microcode [] 0xc8868000 2976 0 keybdev [] 0xc8863000 5492 0 mousedev [] 0xc885a000 22084 0 hid [] 0xc8855000 5856 0 input [keybdev mousedev hid] 0xc884b000 25836 0 usb-uhci [] 0xc8835000 77152 1 usbcore [hid usb-uhci] 0xc881d000 85704 3 ext3 [] 0xc880d000 50572 3 jbd [ext3] 0xc0354fc0 0 1 kernel_module [] ==================================================================== ======= >> module -f | more EXPORTED MODULE SYMBOLS: ==================================================================== ======= Module: e100 Number of exported symbols: 69 ADDR NAME [MODULE] -------------------------------------------------------------------------- - 4-15 - ::ctfin fo ::modin fo ::modct l >::ctfinfo MODULE unix krtld genunix platmod SUNW,UltraSPARC-III specfs TS TS_DPTBL ufs fssnap_if rootnex options sad pseudo schppm xcalppm ebus pcisch ssd scsi fcp fctl >::modinfo ID LOADADDR 0 1000000 1 105db8c 2 1070268 3 1170cd0 4 1171200 5 0 6 117e000 CTFDATA 300000b6000 0 30000100000 3000012a000 30000130000 3000021a000 3000025e000 3000012b87c 300002fe000 3000012ba48 30000306000 30000135f60 3000012be64 3000012bf2c 300000bf260 3000030c000 300000bf30c 30000330000 30000388000 3000035c000 3000037c000 30000304188 CTFSIZE 37472 0 165890 6267 17123 16370 11554 460 24965 703 10438 115 197 150 171 11995 879 18560 20851 14540 19078 6172 SIZE REV MODULE NAME 97d84 0 unix (?) 1873a 0 krtld (?) 14a31f 0 genunix (?) 709 0 platmod (?) cac9 0 SUNW,UltraSPARC-III (?) 0 0 cl_bootstrap (?) 43db 1 specfs (filesystem for specfs) 0xc88e52e0 0xc88e92c0 0xc88ee60c 0xc88e9d20 0xc88e9980 0xc88e6d20 0xc88e9900 0xc88e3de0 0xc88e9680 0xc88e7e20 0xc88ee140 0xc88e74b0 0xc88e86f0 0xc88e2c50 0xc88e5220 e100_configure_device e100_force_speed_duplex_to_phy e100_full_driver_name e100_eeprom_read e100_handle_zlock e100_alloc_non_tx_cmd e100_update_link_state e100_tx_srv e100_phy_set_speed_duplex e100_config_promisc __insmod_e100_S.data_L7404 e100_wait_cus_idle e100_mdi_read e100_close e100_isolate_driver [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] [e100] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 >> module -p | more c88e52e0 e100_configure_device [e100] c88e92c0 e100_force_speed_duplex_to_phy [e100] c88ee60c e100_full_driver_name [e100] c88e9d20 e100_eeprom_read [e100] c88e9980 e100_handle_zlock [e100] c88e6d20 e100_alloc_non_tx_cmd [e100] c88e9900 e100_update_link_state [e100] c88e3de0 e100_tx_srv [e100] c88e9680 e100_phy_set_speed_duplex [e100] c88e7e20 e100_config_promisc [e100] c88ee140 __insmod_e100_S.data_L7404 [e100] c88e74b0 e100_wait_cus_idle [e100] c88e86f0 e100_mdi_read [e100] c88e2c50 e100_close [e100] c88e5220 e100_isolate_driver [e100] c88e7a10 e100_config_init_82557 [e100] c88e7be0 e100_force_config [e100] c88e32d0 e100_hw_init [e100] c88e4ba0 e100_exec_non_cu_cmd [e100] c88e3930 e100_watchdog [e100] c88e4290 e100_refresh_txthld [e100] c88e9800 e100_phy_init [e100] マウントされているファイルシステムに関する情報を出力する crash> mount mount VFSMOUNT SUPERBLK TYPE DEVNAME DIRNAME c1544100 c1542000 rootfs rootfs / c1544380 c148b000 ext3 /dev/root / c1544340 c1542800 proc /proc /proc c1544300 c148bc00 usbdevfs usbdevfs /proc/bus/usb c15443c0 c1530c00 ext3 /dev/hda1 /boot c1544400 c1530400 devpts none /dev/pts c1544440 c7faa000 tmpfs none /dev/shm c1544480 c7faa400 ext3 /dev/hda2 /var crash> mount –f VFSMOUNT SUPERBLK TYPE DEVNAME c1544100 c1542000 rootfs rootfs OPEN FILES No open files found VFSMOUNT SUPERBLK TYPE c1544380 c148b000 ext3 OPEN FILES DENTRY INODE TYPE c12bae00 c12c2b00 REG -- MODCTL 142c5f0 143fa58 1440258 148c5b8 148f208 3000005bf08 3000005be88 3000005be08 3000005bd88 3000005bd08 3000005bb88 3000005bb08 3000005ba88 3000005ba08 3000005b908 3000005b988 3000005b888 3000005b808 3000005b788 3000005b708 3000005b688 3000005b608 o DEVNAME DIRNAME /dev/root / PATH lib/tls/libc-2.3.2.so - 4-16 - 0 38dc 8dc 3493e 1c7 1b3a 210 0 181a 64b 434 2d85 15cb 11b05 23063 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 swapgeneric (?) TS (time sharing sched class) TS_DPTBL (Time sharing dispatch table) ufs (filesystem for ufs) fssnap_if (File System Snapshot Interface) rootnex (sun4u root nexus 1.95) options (options driver) dma (?) sad (STREAMS Administrative Driver ') pseudo (nexus driver for 'pseudo') schppm (schizo pm driver v1.2) xcalppm (platform pm driver v1.18) ebus (ebus nexus driver 1.44) pcisch (PCI Bus nexus driver 1.214) ssd (SCSI SSA/FCAL Disk Driver 1.418) >::modctl ::fsinf DIRNAME / 0 1183ba8 1186d20 1186db0 11b8cae 11b8dce 11ba4fb 0 11babd7 11bc151 11bc62a 11bc97e 11bf2a3 11c0456 11d05fb MODULE BITS FLAGS FILE 143a720 0x00 /platform/sun4u/kernel/sparcv9/unix 143fb00 0x00 misc/sparcv9/krtld 14402f0 0x00 genunix 148c658 0x00 misc/platmod 148f2b0 0x00 cpu/SUNW,UltraSPARC-III 0 0x00 misc/cl_bootstrap 3000006fe08 li 0x00 fs/specfs 0 0x00 misc/swapgeneric 3000006fb88 li 0x00 sched/TS 3000006fa48 li 0x00 sched/TS_DPTBL 3000006f908 li 0x00 fs/ufs 3000006f7c8 li 0x00 misc/fssnap_if 3000006f688 li 0x00 drv/rootnex 3000006f548 li 0x00 drv/options 0 0x00 drv/dma 3000006f2c8 li 0x00 drv/sad 3000006f188 li 0x00 drv/pseudo 3000006f048 li 0x00 drv/schppm 3000006ef08 li 0x00 drv/xcalppm 3000006edc8 li 0x00 drv/ebus 3000006ec88 li 0x00 drv/pcisch 3000006eb48 li 0x00 drv/ssd > ::fsinfo VFSP TYP 146bef8 2 3000026f688 5 3000026f5e8 15 3000026f4a8 12 3000026f368 4 3000026f2c8 4 3000026f228 4 3000026f188 11 3000026f0e8 4 3000026f048 4 3000026efa8 11 3000026ef08 2 3000026edc8 17 3000026ed28 17 3000026ebe8 17 3000026eb48 4 3000026eaa8 4 3000026e3c8 300032f5e10 7 3000026e008 4 DATA OPS MOUNT 30000041dc8 ufs_vfsops / 300008b8b10 prvfsops /proc 30000273868 mntvfsops /etc/mnttab 0 fdvfsops /dev/fd 30000b948e8 nmvfsops /etc/sysevent/devfsad... 30000b94a28 nmvfsops /etc/sysevent/syseven... 30000b947a8 nmvfsops /etc/sysevent/syseven... 30000973290 tmp_vfsops /var/run 30000b943e8 nmvfsops /etc/sysevent/picleve... 300013c3cf0 nmvfsops /var/run/picld_door 300013d7c48 tmp_vfsops /tmp 30000041508 ufs_vfsops /space 3000026d558 auto_vfsops /net 3000026d4a8 auto_vfsops /home 3000026d3f8 auto_vfsops /xfn 300015cdd08 nmvfsops /var/run/syslog_door 300015cdbc8 nmvfsops /var/run/name_service... 4 300015cd588 nmvfsops /etc/saf/_cmdpipe 300032b4aa8 nfs_vfsops /vol 3000320d328 nmvfsops /tmp/.X11-pipe/X0 c12bab00 c5c00880 c59a2b80 c6eadc00 c6eada00 c6ead980 c6ead880 c7031a00 c7031680 c7031580 c7031480 c609f780 c609f700 c12c2100 c5c0c680 c5911480 c6e44180 c6e73d00 c6e73b00 c6e73700 c6f27500 c6fd6680 c6fd6280 c703bd80 c6064680 c6064480 REG REG REG REG REG REG REG REG REG REG REG REG REG lib/ld-2.3.2.so opt/es7000/bin/krnl-1 usr/share/locale/ja/LC_MESSAGES/libc.mo usr/lib/gconv/libJIS.so usr/lib/gconv/EUC-JP.so usr/lib/gconv/gconv-modules.cache usr/lib/locale/locale-archive lib/libnss_files-2.3.2.so lib/libdl-2.3.2.so lib/libtermcap.so.2.0.8 bin/bash lib/security/pam_limits.so usr/lib/libcrack.so.2.7 crash> mount –i FSMOUNT SUPERBLK TYPE DEVNAME c1544100 c1542000 rootfs rootfs DIRTY INODES No dirty inodes found 300032f5af0 10 3000321f6b0 lo_vfsops /home/sasaki DIRNAME / VFSMOUNT SUPERBLK TYPE c1544380 c148b000 ext3 DIRTY INODES c12c2b08 c12c2908 c12c2508 c12c2108 c12b8c88 c5c0c688 DEVNAME DIRNAME /dev/root / VFSMOUNT SUPERBLK TYPE c1544340 c1542800 proc DIRTY INODES No dirty inodes found DEVNAME /proc DIRNAME /proc VFSMOUNT SUPERBLK TYPE DEVNAME DIRNAME c1544300 c148bc00 usbdevfs usbdevfs /proc/bus/usb DIRTY INODES ネットワーク情報を表示する crash> net net NET_DEVICE NAME c037fec0 lo c7e49000 eth0 crash> net -a IP ADDRESS 172.24.33.254 (REACHABLE) -- IP ADDRESS(ES) 127.0.0.1 172.24.33.85 ::netst at ::ire HW TYPE ETHER HW ADDRESS DEVICE STATE 00:09:b7:a0:43:80 eth0 crash> net -s PID: 895 TASK: c5934000 CPU: 0 No open sockets. ::tcpb 02 COMMAND: "krnl-1" - 4-17 - >::netstat TCPv4 St Local Address Remote Address 000003000320c090 0 172.24.33.60.23 172.24.32.13.3195 TCPv6 St Local Address Remote Address UDPv4 St Local Address Remote Address UDPv6 St Local Address Remote Address AF_UNIX Type Vnode Conn Local Addr Remote Addr 300018468f8 stream-ord 00000300098f96a0 0000000000000000 /var/run/smc898/cmdsock (none) 30001846ac0 stream-ord 0000000000000000 0000000000000000 (none) (none) 30001846c88 stream-ord 0000030003290de0 0000000000000000 /tmp/.X11-unix/X0 (none) 30001846e50 dgram 0000000000000000 0000000000000000 (none) (none) 30001847018 dgram 000003000184a2e8 0000000000000000 net_conn.sock (none) 300018471e0 dgram 000003000184a4d0 0000000000000000 net_inp.sock (none) 300018473a8 dgram 0000000000000000 0000000000000000 (none) (none) 30001847570 dgram 0000000000000000 0000000000000000 (none) (none) >::ire ADDR 30000b78148 30000b783c8 30000b78508 30000b78648 30000b78a08 30000b78b48 30000b78c88 30000b78dc8 30000b78f08 30000b79048 30000b79188 30000b792c8 30000b79408 30000b79548 30000b79688 30000b797c8 30000b79908 30000b79a48 30000b79b88 30000b79cc8 30000b79e08 300034ada50 >::tcpb TCPBAddr 000003000085f800 00000300013c31d8 00000300013c3318 00000300013c2cd8 00000300013c2e18 00000300013c2a58 00000300013c2918 00000300013c27d8 00000300013c2698 00000300013c2558 00000300013c2198 00000300013c2058 00000300014b3e60 00000300014b3be0 00000300014b3960 00000300014b36e0 00000300014b3460 00000300014b2e20 00000300014b2920 00000300014b27e0 00000300014b26a0 00000300014b2560 SRC 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 0.0.0.0 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 172.24.33.60 127.0.0.1 172.24.33.60 St -5 -3 -5 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 -3 IP v6 v4 v4 v6 v6 v4 v6 v6 v4 v6 v4 v6 v6 v6 v6 v6 v6 v4 v4 v4 v6 v6 DST 172.24.33.254 172.24.32.13 172.24.33.106 172.24.33.11 224.0.0.0 0.0.0.0 255.255.255.255 172.24.0.0 0.0.0.0 255.255.255.255 172.24.255.255 172.24.33.0 172.24.0.0 172.24.255.255 172.24.33.60 172.24.33.0 172.24.33.0 172.24.33.255 172.24.33.255 0.0.0.0 127.0.0.1 224.0.0.2 TCPAddr 0000030000049770 0000030000049b50 0000030000049390 0000030000048fb0 0000030000048bd0 00000300000487f0 0000030000048410 0000030000048030 00000300014b7b58 00000300014b7778 00000300014b7398 00000300014b6fb8 00000300014b6bd8 00000300014b67f8 00000300014b6418 00000300014b6038 00000300014a1b60 00000300014a1780 00000300014a13a0 00000300014a0fc0 00000300014a0be0 00000300014a0800 値の表示 p crash> p jiffies print >> jiffies = $1 = 843846 p *)0xc5c14000)->files.fd).f_flags & 0x8000 pb, pd, 32768 print (*((struct task_struct -- po, px アクティブプロセスを出力する ps crash> ps PID PPID CPU TASK ST %MEM 0 0 0 c03b6000 RU 0.0 VSZ 0 RSS COMM 0 [swapper] ps >> ps Address Uid Pid PPid Stat Flags SIZE:RSS Command ----------------------------------------------------------------------------- - 4-18 - ::ps > ::ps S PID R 0 PPID 0 PGID 0 SID 0 UID FLAGS ADDR NAME 0 0x00000019 0000000001438a38 sched 1 2 3 4 5 6 7 8 9 13 75 172 173 520 524 568 582 591 619 628 635 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c7fa4000 c1468000 c154e000 c154c000 c1466000 c1464000 c1462000 c1460000 c1554000 c7120000 c7f54000 c7e3c000 c1324000 c7da2000 c6b4c000 c666c000 c65f4000 c65c4000 c6288000 c5e74000 c701c000 RU RU RU IN RU RU RU RU IN RU IN IN IN RU RU IN IN RU RU RU IN 0.4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.5 0.4 1.2 0.7 0.5 2.8 0.4 0.3 1520 0 0 0 0 0 0 0 0 0 0 0 0 1572 1520 3776 2136 1576 6056 1560 1492 508 0 0 0 0 0 0 0 0 0 0 0 0 632 468 1596 888 628 3656 564 424 init [keventd] [kapmd] [ksoftirqd/0] [kswapd] [kscand] [bdflush] [kupdated] [mdrecoveryd] [kjournald] [khubd] [kjournald] [kjournald] syslogd klogd sshd xinetd crond xfs atd mingetty c03b6000 0 0 0 0x00 0x00000000 0:0 swapper c7fa4000 0 1 0 0x00 0x00000100 380:127 init c1468000 0 2 1 0x00 0x00000040 0:0 keventd c154e000 0 3 1 0x00 0x00000040 0:0 kapmd c154c000 0 4 1 0x01 0x00000040 0:0 ksoftirqd/0 c1462000 0 7 1 0x00 0x00000040 0:0 bdflush c1466000 0 5 1 0x00 0x00000840 0:0 kswapd c1464000 0 6 1 0x00 0x00000040 0:0 kscand c1460000 0 8 1 0x00 0x00000040 0:0 kupdated c1554000 0 9 1 0x01 0x00000040 0:0 mdrecoveryd c7120000 0 13 1 0x00 0x00000040 0:0 kjournald c7f54000 0 75 1 0x01 0x00000040 0:0 khubd c7e3c000 0 172 1 0x01 0x00000040 0:0 kjournald c1324000 0 173 1 0x01 0x00000040 0:0 kjournald c7da2000 0 520 1 0x00 0x00000040 393:158 syslogd c6b4c000 0 524 1 0x00 0x00000140 380:117 klogd c666c000 0 568 1 0x01 0x00000140 944:399 sshd c65f4000 0 582 1 0x01 0x00000140 534:222 xinetd c65c4000 0 591 1 0x00 0x00000040 394:157 crond c6288000 43 619 1 0x00 0x00000140 1514:914 xfs c5e74000 0 628 1 0x00 0x00000040 390:141 atd c701c000 0 635 1 0x01 0x00000100 373:106 mingetty c6ef8000 0 636 1 0x01 0x00000100 374:107 mingetty c6ba4000 0 637 1 0x01 0x00000100 379:107 mingetty c5e4c000 0 638 1 0x01 0x00000100 378:108 mingetty c5e4a000 0 639 1 0x01 0x00000100 380:108 mingetty c5e48000 0 640 1 0x01 0x00000100 380:108 mingetty c6106000 0 641 582 0x00 0x00000100 433:176 in.telnetd c60ce000 0 642 641 0x01 0x00000100 591:292 login c6014000 500 643 642 0x01 0x00000100 1312:335 bash c5d26000 500 678 643 0x01 0x00000100 1273:254 su c5cca000 0 679 678 0x01 0x00000100 1312:349 bash c5c16000 0 764 582 0x01 0x00000100 435:179 in.telnetd c5c9e000 0 765 764 0x01 0x00000100 591:266 login c5a14000 0 766 765 0x01 0x00000100 1313:344 bash c59f0000 0 805 582 0x00 0x00000100 433:176 in.telnetd c5998000 0 806 805 0x01 0x00000100 592:267 login c595a000 0 807 806 0x01 0x00000100 1337:360 bash c5934000 0 895 679 0x00 0x00100000 343:60 krnl-1 ----------------------------------------------------------------------------39 processes found - 4-19 - ::ptree R 3 0 R 2 0 R 1 0 R 28676 1 R 28686 28676 R 28685 28676 R 11515 1 R 591 1 R 582 1 R 581 1 R 588 581 R 574 1 R 568 1 R 567 1 R 551 1 R 555 551 R 528 rpc.bootparamd R 526 in.rarpd R 492 1 R 26357 492 R 26355 492 0 0 0 0 0 0 28676 28676 28676 28676 28676 28676 11506 0 591 591 582 582 581 581 581 581 574 574 568 568 567 567 551 551 555 555 1 528 1 526 492 492 26357 26357 26355 26355 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x00020019 000003000092a008 fsflush 0x00020019 000003000092aa20 pageout 0x00004008 000003000092b438 init 0x00020008 0000030009c4eb18 isdca 0x10024008 000003006e8dd540 istcpin 0x10024008 000003006e8d5550 istcpin 0x00004008 0000030009919520 java 0x00000008 0000030002f7c0b8 sshd 0x00004008 0000030002eee0b0 ttymon 0x00014008 0000030000b1d440 sac 0x00014008 000003000186f4c0 ttymon 0x00014008 000003000187d4b8 vold 0x00020008 000003000199f4d0 snmpXdmid 0x00000008 0000030002edc0a8 dmispd 0x00010008 0000030001916ab0 snmpdx 0x00004008 0000030001916098 mibiisa 528 0 0x00000008 0000030002e56068 526 0 0x00000008 000003000187caa0 0 0x00010008 0000030001636048 dtlogin 0 0x00004008 000003000199eab8 fbconsole 0 0x00000008 00000300017ee080 dtlogin > ::ptree 0000000001438a38 sched 000003000092a008 fsflush 000003000092aa20 pageout 000003000092b438 init 0000030009c4eb18 isdca 000003006e8dd540 istcpin 000003006e8d5550 istcpin 0000030009919520 java 0000030002f7c0b8 sshd 0000030002eee0b0 ttymon 0000030000b1d440 sac 000003000186f4c0 ttymon 000003000187d4b8 vold 000003000199f4d0 snmpXdmid 0000030002edc0a8 dmispd 0000030001916ab0 snmpdx 0000030001916098 mibiisa 0000030002e56068 rpc.bootparamd 000003000187caa0 in.rarpd 0000030001636048 dtlogin 000003000199eab8 fbconsole 00000300017ee080 dtlogin 000003000187c088 dtgreet 0000030002f7cad0 Xsun 00000300017b2070 spo_test 000003000186eaa8 shutrcv 00000300017b2a88 atokmngdaemon 0000030002e56a80 cycliclog 0000030002e57498 par 00000300017eea98 net 00000300017ef4b0 out 00000300017fc078 inp 00000300017fca90 tim 00000300017fd4a8 hdl 00000300016c6a68 htt 0000030002e78a78 htt_server 000003000170c058 jserver 0000030002e79490 jserver_m 000003000170ca70 dpkeyserv 0000030001648040 keyserver 000003000155ea48 calserver 000003000170d488 sendmail 00000300016c6050 sendmail 0000030000b1ca28 utmpd 0000030001636a60 popper 0000030001648a58 powerd 000003000155e030 nscd 00000300015c4a50 cron 000003000155f460 syslogd 000003000125a018 sh 00000300013a4020 ntpdate 00000300013a5450 automountd 00000300014f4028 lockd 00000300014f4a40 statd 00000300013a4a38 inetd 0000030002edcac0 in.telnetd 000003000336b500 ksh 00000300033974f8 sh 00000300099180f0 sh 000003000333f4f0 reboot 00000300034c80d8 rpc.ttdbserverd 0000030000b1c010 rpcbind 000003000125aa30 picld 000003000125b448 syseventd ページテーブルエントリを変換する pte crash> pte d8e067 PTE -- -- -- -- -- -- PHYSICAL FLAGS d8e067 d8e000 (PRESENT|RW|USER|ACCESSED|DIRTY) ページフレーム番号をそのバイト値に変換する ptob crash> ptob 512a 512a: 512a000 16 進物理アドレスをカーネルの仮想アドレスに変換する ptov crash> ptov 56e000 VIRTUAL PHYSICAL c056e000 56e000 指定された領域の書式付きメモリーダンプを出力する rd crash> > rd 0xc010cbc0 10 dump dump 0xc010cbc0 10 dump c010cbc0: 7e2005c6 8b01c03e 8b042444 44892840 .. ~>...D$..@(.D md 0xc010cbc0: 7e2005c6 8b01c03e 8b042444 44892840 : .. ~>...D$..@(.D \/ 1 2 3 4 5 6 7 8 9 a b c d e f v123456789abcdef c010cbd0: c9e90424 89fffffe 27bc8df6 00000000 $..........'.... od 0xc010cbd0: c9e90424 89fffffe 27bc8df6 00000000 : $..........'.... 116f1d0: 666f7263 65642063 72617368 2064756d forced crash dum c010cbe0: 0090ec81 9c890000 0xc010cbe0: 0090ec81 9c890000 : ........ コマンドを繰り返す repeat >116f1d0::dump crash> repeat -1 p jiffies -- -- jiffies = $2 = 843846 jiffies = $3 = 843846 - 4-20 - jiffies = $4 = 843846 jiffies = $5 = 843846 ランキュー上のタスクを表示する crash> runq runq RUNQUEUES[0]: c03e5980 ACTIVE PRIO_ARRAY: c03e5e18 [115] PID: 3 TASK: c154e000 PID: 5 TASK: c1466000 PID: 6 TASK: c1464000 PID: 8 TASK: c1460000 PID: 641 TASK: c6106000 PID: 1 TASK: c7fa4000 PID: 13 TASK: c7120000 PID: 520 TASK: c7da2000 PID: 2 TASK: c1468000 PID: 524 TASK: c6b4c000 PID: 7 TASK: c1462000 PID: 591 TASK: c65c4000 PID: 805 TASK: c59f0000 PID: 619 TASK: c6288000 PID: 628 TASK: c5e74000 EXPIRED PRIO_ARRAY: c03e59a0 [121] PID: 895 TASK: c5934000 -- -- -- kgrep CPU: 0 COMMAND: "kapmd" CPU: 0 COMMAND: "kswapd" CPU: 0 COMMAND: "kscand" CPU: 0 COMMAND: "kupdated" CPU: 0 COMMAND: "in.telnetd" CPU: 0 COMMAND: "init" CPU: 0 COMMAND: "kjournald" CPU: 0 COMMAND: "syslogd" CPU: 0 COMMAND: "keventd" CPU: 0 COMMAND: "klogd" CPU: 0 COMMAND: "bdflush" CPU: 0 COMMAND: "crond" CPU: 0 COMMAND: "in.telnetd" CPU: 0 COMMAND: "xfs" CPU: 0 COMMAND: "atd" CPU: 0 COMMAND: "krnl-1" カーネルのアドレス空間で特定の値を検索する search プロセス情況または内部クラッシュ変数をセットする デフォルトのtask をセット,または,デフォルトのtask のアドレスを表示する crash> set set set >> set PID: 895 COMMAND: "krnl-1" deftask Debug components: none TASK: c5934000 CPU: 0 Trace threshold: 0 STATE: TASK_RUNNING (PANIC) Iteration threshold: 10000 crash> set -v scroll: on radix: 10 (decimal) refresh: on print_max: 256 console: (not assigned) debug: 0 core: off hash: on silent: off edit: vi namelist: /opt/dump/data/vmlinux dumpfile: /opt/dump/data/dump.2 タスクシグナルハンドリング PID: 895 TASK: c5934000 CPU: 0 COMMAND: "krnl-1" sig SIGPENDING: yes SIGNAL: 0000000000000080 BLOCKED: 0000000000000000 SIGNAL_STRUCT: c153b9c0 COUNT: 1 SIG SIGACTION HANDLER MASK FLAGS [1] c599a384 SIG_DFL 0000000000000000 0 [2] c599a398 SIG_DFL 0000000000000000 0 [3] c599a3ac SIG_DFL 0000000000000000 0 [4] c599a3c0 SIG_DFL 0000000000000000 0 -- -- -- - 4-21 - [5] c599a3d4 SIG_DFL 0000000000000000 0 [6] c599a3e8 SIG_DFL 0000000000000000 0 [7] c599a3fc SIG_DFL 0000000000000000 0 [8] c599a410 SIG_DFL 0000000000000000 0 [9] c599a424 SIG_DFL 0000000000000000 0 [10] c599a438 SIG_DFL 0000000000000000 0 [11] c599a44c SIG_DFL 0000000000000000 0 [12] c599a460 SIG_DFL 0000000000000000 0 [13] c599a474 SIG_DFL 0000000000000000 0 [14] c599a488 80483b0 0000000000002000 (SA_RESTORER|SA_RESTART) [15] c599a49c SIG_DFL 0000000000000000 0 [16] c599a4b0 SIG_DFL 0000000000000000 0 [17] c599a4c4 SIG_DFL 0000000000000000 0 14000000 構造体の内容を表示する crash> struct kernel_timeval struct struct kernel_timeval { unsigned int tv_sec; unsigned int tv_usec; } SIZE: 8 -- ::offse tof スワップ情報を表示する swap -- crash> swap FILENAME TYPE SIZE /dev/hda5 PARTITION 265032k USED 0k ::swapi nfo PCT PRIORITY 0% > ::swapinfo ADDR 0000030000058af8 -1 VNODE PAGES 30000ba4b08 FREE NAME 65672 65672 /dev/dsk/c1t1d0s1 シンボルをその仮想アドレスに変換する,またはその逆 シンボリックネーム/アドレスの関連情報を表示する crash> sym -l >> findsym system_utsname sym findsym c0100000 (A) _text c0100000 (t) startup_32 ADDR OFFSET SECTION NAME TYPE fsym c01000a5 (t) checkCPUtype c0100133 (t) is486 ================================================================ symbol c0100142 (t) is386 0xc03539e0 0 GLOBAL_DATA system_utsname (unknown) c010018c (t) L6 c010018e (t) ready ================================================================ c010018f (t) check_x87 c01001b6 (t) setup_idt 1 symbol found c01001d3 (t) rp_sidt c01001e0 (T) stack_start c01001e8 (t) int_msg c01001fc (t) ignore_int c010021e (T) idt_descr c0100224 (T) cpu_gdt_descr c0101000 (T) swapper_pg_dir c0102000 (T) pg0 c0103000 (T) pg1 c0104000 (T) pg2 c0105000 (T) pg3 c0106000 (T) empty_zero_page c0107000 (T) _stext c0107000 (T) stext ::nm > ::nm Value |Size |Type 0x0000000000000000|0x0000000000000000|NOTY 0x000000000143a1f4|0x0000000000000000|OBJT 0x0000000001006590|0x0000000000000000|NOTY _fitos_fdtos_table 0x0000000001006e24|0x0000000000000000|NOTY 0x0000000001006e34|0x0000000000000000|NOTY 0x0000000001006610|0x0000000000000000|NOTY _fitos_fdtos_done 0x0000000001006db0|0x0000000000000108|FUNC 0x0000000001006f80|0x0000000000000000|NOTY fast_trap_dummy_call 0x00000000010069dc|0x0000000000000000|NOTY 0x00000000010067d0|0x0000000000000000|NOTY 0x0000000001006f00|0x0000000000000000|NOTY 0x00000000010064f4|0x0000000000000000|NOTY _fitos_fitod_table 0x00000000010069cc|0x0000000000000000|NOTY 0x00000000010067c0|0x0000000000000000|NOTY 0x0000000001006574|0x0000000000000000|NOTY _fitos_fitod_done 0x0000000001006adc|0x0000000000000000|NOTY 0x00000000010068d0|0x0000000000000000|NOTY |Bind |LOCL |LOCL |LOCL |Other|Shndx |0x0 |UNDEF |0x0 |13 |0x0 |6 |Name | |_END_ | |LOCL |0x0 |6 |LOCL |0x0 |6 |LOCL |0x0 |6 |mmu_trap_tl1_1 |mmu_trap_tl1_2 | |LOCL |0x0 |6 |LOCL |0x0 |6 |mmu_trap_tl1 | |LOCL |LOCL |LOCL |LOCL |start1 |start2 |stat_mmu | |0x0 |0x0 |0x0 |0x0 |6 |6 |6 |6 |LOCL |0x0 |6 |LOCL |0x0 |6 |LOCL |0x0 |6 |mark1 |mark2 | |LOCL |0x0 |6 |LOCL |0x0 |6 |done1 |done2 システムデータ システム統計,log_buf を表示する sys crash> sys SYSTEM MAP: /opt/dump/data/map.2 DEBUG KERNEL: /opt/dump/data/vmlinux (2.4.21-9.30AX.dbg) stat info main >> stat sysname : Linux nodename : asianux release : 2.4.21-9.30AX - 4-22 - ::statu > ::status s debugging crash dump /var/crash/virgo/vmcore.1 (64-bit) from virgo operating system: 5.9 Generic_117171-11 (sun4u) CPUS: 1 version : #1 Thu May 27 00:03:41 EDT 2004 machine : i686 domainname : (none) DATE: Thu Jun 17 17:55:20 2004 LOG_BUF: DUMPFILE: /opt/dump/data/dump.2 UPTIME: 02:20:38 panic message: forced crash dump initiated at user request dump content: kernel pages only 4 LOAD AVERAGE: 10.95, 4.09, 1.48 >> info info TASKS: 39 DUMP INFORMATION: NODENAME: asianux RELEASE: 2.4.21-9.30AX VERSION: #1 Thu May 27 00:03:41 EDT 2004 MACHINE: i686 (451 Mhz) MEMORY: 128 MB PANIC: "sysrq" architecture: byte order: pointer size: bytes per word: i386 little 32 4 kernel release: memory size: num phys pages: number of cpus: 2.4.21 134086656 (0G 127M 896K 0Byte) 32736 1 >> main Linux version : 0x00020415 Running linux 2.4.X [0x00020415] /usr/share/sial/lcrash/ps.sial : line 31 : Warning: Non void function should return a value. タスク構造の内容 crash> task task PID: 895 TASK: c5934000 CPU: 0 struct task_struct { state = 0, flags = 1048576, sigpending = 1, addr_limit = { seg = 3221225472 }, exec_domain = 0xc0354d80, need_resched = 1, ptrace = 0, lock_depth = -1, cpu = 0, real_stack = 0xc5934000, virtual_stack = 0x0, user_pgd = 0x0, prio = 121, static_prio = 120, run_list = { next = 0xc03e5d80, prev = 0xc03e5d80 }, array = 0xc03e59a0, sleep_avg = 496, last_run = 831028, policy = 0, cpus_allowed = 4294967295, time_slice = 10, first_time_slice = 0, usage = { counter = 5 }, tasks = { COMMAND: "krnl-1" task ::task >> task ADDR UID PID PPID STATE FLAGS CPU NAME ::task_ > ::task ADDR TASKID PROJID REFCNT FLAGS 00000300003f3d18 156 1 1 0x00000000 00000300003f3db8 98 3 1 0x00000000 00000300003f3e08 158 1 2 0x00000000 swapper 00000300003f3e58 155 3 1 0x00000000 ========================================================== 00000300003f3ea8 127 3 3 0x00000000 ============ 00000300003f3ef8 1 0 53 0x00000000 1 active task struct found 00000300003f3f48 0 0 3 0x00000000 ========================================================== =========== 0xc03b6000 0 0 4294967295 - 4-23 - 0 0 - entry next = 0xc03b6060, prev = 0xc595a060 }, ptrace_children = { next = 0xc5934068, prev = 0xc5934068 }, ptrace_list = { next = 0xc5934070, prev = 0xc5934070 }, mm = 0xc5c86800, active_mm = 0xc5c86800, タイマキューデータ crash> timer timer TVEC_BASES[0]: c03560a0 JIFFIES 843846 EXPIRES TIMER_LIST FUNCTION 844259 c042d680 c01acf40 844259 c042d680 c01acf40 844903 c151f634 c884dd60 845250 c6289ef4 c012bb40 845347 c5e75f74 c012bb40 845443 c593419c c0125cf0 845910 c04558c0 c0229740 846129 c03b1a28 c021bc90 847435 c7e492b8 c88e3930 851240 c03b1420 c022e0c0 874095 c04558e0 c0229a10 900000 c0455460 c0222110 900454 c0454680 c0215a40 900454 c0455fa0 c022ef30 903777 c042c3c0 c01ab170 1080073 c03b0e60 c0225570 1486502 c6d9fc58 c02470c0 1489002 c135b1d8 c02470c0 1495107 c6d9ebd8 c02470c0 -- <rs_timer> <rs_timer> <rh_int_timer_do> <process_timeout> <process_timeout> <it_real_fn> <rt_check_expire> <neigh_periodic_timer> <e100_watchdog> <peer_check_expire> <rt_secret_rebuild> <rif_check_expire> <flow_cache_new_hashrnd> <ipfrag_secret_rebuild> <blank_screen> <psched_tick> <tcp_keepalive_timer> <tcp_keepalive_timer> <tcp_keepalive_timer> union 構造体の内容 crash> union bdflush_param union union bdflush_param { struct { int nfract; int ndirty; int dummy2; int dummy3; int interval; int age_buffer; int nfract_sync; int nfract_stop_bdflush; int dummy5; } b_un; unsigned int data[9]; } SIZE: 36 仮想メモリ情報を表示する crash> vm vm PID: 895 TASK: c5934000 CPU: 0 COMMAND: "krnl-1" MM PGD RSS TOTAL_VM c5c86800 c58d0000 240k 1372k VMA START END FLAGS FILE -- ::offse tof -- - 4-24 - c5956474 c5956584 c5956188 c5956430 c5956a4c c59563ec c5956694 c5956254 c5956540 8048000 8049000 b74a2000 b75d4000 b75d7000 b75ea000 b75eb000 b7600000 bfffa000 8049000 804a000 b75d4000 b75d7000 b75da000 b75eb000 b7600000 b7601000 c0000000 1875 101873 75 100073 100073 100073 875 100873 100177 crash> mv PID: 895 MM c5c86800 VMA c5956474 VIRTUAL 8048000 VMA c5956584 VIRTUAL 8049000 VMA c5956188 VIRTUAL b74a2000 b74a3000 b74a4000 b74a5000 b74a6000 b74a7000 b74a8000 b74a9000 b74aa000 –p TASK: c5934000 CPU: 0 PGD RSS TOTAL_VM c58d0000 240k 1372k START END FLAGS 8048000 8049000 1875 PHYSICAL 5200000 START END FLAGS 8049000 804a000 101873 PHYSICAL 558a000 START END FLAGS b74a2000 b75d4000 75 PHYSICAL 70eb000 70d9000 70d8000 70d7000 70d6000 70d5000 70d4000 70d3000 70d2000 crash> vm –v ID: 895 TASK: c5934000 CPU: 0 struct vm_area_struct { vm_mm = 0xc5c86800, vm_start = 134512640, vm_end = 134516736, vm_next = 0xc5956584, vm_page_prot = { pgprot = 37 }, vm_flags = 6261, vm_rb = { rb_parent = 0xc595659c, rb_color = 1, rb_right = 0x0, rb_left = 0x0 }, vm_next_share = 0x0, vm_pprev_share = 0xc59565ac, vm_ops = 0xc0371efc, vm_pgoff = 0, vm_file = 0xc5913580, vm_raend = 0, vm_private_data = 0x0 crash> vm -m PID: 895 TASK: c5934000 CPU: 0 struct mm_struct { mmap = 0xc5956474, /opt/es7000/bin/krnl-1 /opt/es7000/bin/krnl-1 /lib/tls/libc-2.3.2.so /lib/tls/libc-2.3.2.so /lib/ld-2.3.2.so /lib/ld-2.3.2.so COMMAND: "krnl-1" FILE /opt/es7000/bin/krnl-1 FILE /opt/es7000/bin/krnl-1 FILE /lib/tls/libc-2.3.2.so COMMAND: "krnl-1" COMMAND: "krnl-1" - 4-25 - mm_rb = { rb_node = 0xc5956404 }, mmap_cache = 0xc5956188, free_area_cache = 1073741824, non_executable_cache = 3076431872, pgd = 0xc58d0000, mm_users = { counter = 1 }, mm_count = { counter = 1 }, map_count = 9, mmap_sem = { count = 0, wait_lock = <incomplete type>, wait_list = { next = 0xc5c86828, prev = 0xc5c86828 crash> vm -R 75 PID: 895 TASK: c5934000 CPU: 0 COMMAND: "krnl-1" MM PGD RSS TOTAL_VM c5c86800 c58d0000 240k 1372k VMA START END FLAGS FILE c5956188 b74a2000 b75d4000 75 /lib/tls/libc-2.3.2.so 仮想アドレスを物理アドレスに変換する crash> vtop c5934000 vtop VIRTUAL PHYSICAL c5934000 5934000 vtop ::vtop >> vtop c5934000 VADDR KADDR PADDR PAGE DIRECTORY: c0101000 PGD: c0101c58 => 58001e3 PAGE: 5800000 (4MB) ========================================= PTE PHYSICAL FLAGS 0 0 (no mapping) ========================================= PAGE PHYSICAL c1138390 5934000 MAPPING 0 0xc5934000 0xc5934000 0x5934000 > ::vtop virtual 30000058af8 mapped to physical 1f0eaaf8 PFN 22836 INDEX CNT FLAGS 0 1 1400000 待機キューリスト上のタスクリストを表示する waitq crash> waitq buffer_wait -- ::queue wait queue "buffer_wait" (c0373108) is empty - 4-26 - > ::queue ADDR MODULE FLAGS NBLK 00000300008f2008 fifostrrhead 044032 0 0000000000000000 00000300008f2290 usbkbm 002032 0 0000000000000000 00000300008f2518 USB HID STREAMS driver 201032 0 0000000000000000 00000300008f27a0 conskbd 04c032 0 0000000000000000 00000300008f2a28 usbms 002032 0 0000000000000000 00000300008f2cb0 USB HID STREAMS driver 201032 0 0000000000000000 00000300008f2f38 consms 042032 0 0000000000000000 00000300008f31c0 tcp 1100832 0 0000000000000000 00000300008f3448 ip 1202032 0 0000000000000000 00000300008f36d0 ip 042032 0 0000000000000000 00000300008f3958 conskbd 20c032 0 0000000000000000 00000300008f3be0 wc 042032 0 0000000000000000 00000300008bc010 strrhead 044032 0 0000000000000000 00000300008bc298 timod 1000832 0 0000000000000000 00000300008bc520 ip 002032 0 0000000000000000 00000300008bc7a8 eri 204032 0 0000000000000000 00000300008bca30 ip 042032 0 0000000000000000 00000300008bccb8 strrhead 044032 0 0000000000000000 00000300008bcf40 00000300008bd1c8 00000300008bd450 00000300008bd6d8 00000300008bd960 00000300008bdbe8 0000030001066018 00000300010662a0 0000030001066528 00000300010667b0 0000030001066a38 0000030001066cc0 0000030001066f48 00000300010671d0 0000030001067458 00000300010676e0 0000030001067968 0000030001067bf0 000003000147e020 000003000147e2a8 000003000147e530 000003000147e7b8 000003000147ea40 000003000147ecc8 000003000147ef50 000003000147f1d8 000003000147f460 データのシンボルテーブルまたは型情報を表示する crash> whatis linux_binfmt whatis struct linux_binfmt { struct linux_binfmt *next; struct module *module; int (*load_binary)(struct linux_binprm *, struct pt_regs *); int (*load_shlib)(struct file *); int (*core_dump)(long int, struct pt_regs *, struct file *); long unsigned int min_coredump; } SIZE: 24 whatis >> whatis linux_binfmt struct linux_binfmt { struct linux_binfmt *next; struct module *module; int (*load_binary)(); int (*load_shlib)(); int (*core_dump)(); long unsigned int min_coredump; }; ::whati >> defcpu -- s メモリへの書き込み wr crash> wr my_debug_flag 1 -- デフォルトのCPU をセット,または,デフォルトのCPU を表示する -- defcpu No default cpu set コマンドヒストリーをセットまたは表示する -- history >> history -- 1: print 2: help print 3: help 4: help eavl 5: help ? 6: ? - 4-27 - ip strrhead ttcompat ldterm wc strrhead strrhead timod udp timod udp timod tcp arp arp eri ip ip tl strrhead timod tl strrhead timod tcp ip udp 1202032 044032 000832 000832 202032 044032 044032 1000832 1000832 1000832 1000832 1000832 1100832 1002032 1002032 204032 042032 1202032 208832 044032 1000832 208832 044030 1000832 1100832 1202032 1000832 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 0 0000000000000000 動的にライブラリをロードする -- ldcmds -- livedum -- ライブシステムメモリからダンプを生成する -- p スタックトレースを生成する -- mktrace -- mt mmap_list 内のエントリの関連情報を表示する -- mmap -- >> mmap c03b6000 ADDR MM_COUNT MAP_COUNT MMAP =========================================== 0xc03b6000 4294967295 0 0 =========================================== 1 active mm_struct struct found オープンしたネームリストをリストする/追加する -- -- namelis >> namelist t INDEX NAMELIST nmlist ================================================= 0 kerntypes.2 ================================================= The current namelist is kerntypes.2 (0) page_list 内のエントリのページ構造から関連情報を表示する -- page >> page | more ADDR PGNO COUNT FLAGS VIRTUAL ================================================= 0xc1000030 0 0 0x8000 0xc0000000 0xc1000068 1 0 0x8000 0xc0001000 0xc10000a0 2 0 0x8000 0xc0002000 0xc10000d8 3 0 0x8000 0xc0003000 0xc1000110 4 0 0x8000 0xc0004000 0xc1000148 5 0 0x8000 0xc0005000 0xc1000180 6 0 0x8000 0xc0006000 0xc10001b8 7 0 0x8000 0xc0007000 0xc10001f0 8 0 0x8000 0xc0008000 0xc1000228 9 0 0x8000 0xc0009000 0xc1000260 10 0 0x8000 0xc000a000 0xc1000298 11 0 0x8000 0xc000b000 0xc10002d0 12 0 0x8000 0xc000c000 0xc1000308 13 0 0x8000 0xc000d000 0xc1000340 14 0 0x8000 0xc000e000 0xc1000378 15 0 0x8000 0xc000f000 0xc10003b0 16 0 0x8000 0xc0010000 - 4-28 - ::page > ::page PAGE 00000700024d0ec8 0000070002124428 00000700024d0f40 00000700024d0fb8 000007000223bb90 0000070002167b38 00000700024d1030 0000070002267060 00000700024d10a8 000007000252d808 00000700025f3670 00000700024d1120 0000070002247620 0000070002376758 00000700024d1198 000007000264d490 000007000241c6d0 00000700024d1210 VNODE 142b7b0 300032f56a0 142b7b0 142b7b0 3006f004398 300032f56a0 142b7b0 3010b70f080 142b7b0 3000026e658 3000026e978 142b7b0 3000026ee78 3000026e158 142b7b0 3000190d840 3010b6cf898 142b7b0 OFFSET 30002f1a000 600133f1160000 30002f1c000 30002f1e000 0 60013322b30000 30002f20000 0 30002f22000 60002f2cd40000 60002d90010000 30002f24000 60002b05030000 60006560810000 30002f26000 0 0 30002f28000 SELOCK LCT COW IO FS ST 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 80 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 80 1 0 0 0 0 0 0xc10003e8 0xc1000420 0xc1000458 17 18 19 0 0 0 0x8000 0xc0011000 0x8000 0xc0012000 0x8000 0xc0013000 0000070002326118 0000070002445e18 00000700024d1288 00000700026d4d00 crash dump report (kernel failure が起こったときのシステムの状態等)を表示する -- report ======================= LCRASH CORE FILE REPORT ======================= GENERATED ON: Fri Jul 15 16:25:39 2005 TIME OF CRASH: Thu Jun 17 17:55:18 2004 PANIC STRING: sysrq MAP: map.2 DUMP: dump KERNTYPES: kerntypes.2 ================ COREFILE SUMMARY ================ The system died due to a software failure. =================== UTSNAME INFORMATION =================== sysname nodename release version machine domainname : : : : : : Linux asianux 2.4.21-9.30AX #1 Thu May 27 00:03:41 EDT 2004 i686 (none) =============== LOG BUFFER DUMP =============== 4 ==================== CURRENT SYSTEM TASKS ==================== ADDR UID PID PPID STATE FLAGS CPU NAME ================================================================== 0xc03b6000 0 0 4294967295 0 0 - swapper =========================== STACK TRACE OF FAILING TASK =========================== - 4-29 - -- 300032f56a0 300032f52e0 142b7b0 3000026e478 6001337a050000 600135761c0000 30002f2a000 6000336c5d0000 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ================================================================ STACK TRACE FOR TASK: 0xc5934000 (krnl-1) 0 do_coprocessor_error [0xc010cbc0] 1 restore_i387_fxsave+36 [0xc0112bc4] 2 restore_i387+120 [0xc0112c98] 3 restore_sigcontext+270 [0xc010b1de] 4 sys_sigreturn+204 [0xc010b2cc] 5 no_timing+5 [0xc03b80d1] 6 LKST_ETYPE_SYSCALL_ENTRY_HEADER_hook+53 [0xc03b8036] ================================================================ Live dump を生成する,または,ダンプサイズを小さくする -- savedum -- p バイト単位のデータタイプのサイズを表示し,加えて,構造体メンバーへのオフセットを表示する -- sizeof >> sizeof page ::sizeo offset Size of "page": 56 bytes f sial マクロをアンロードする -- unload unload vi セッションを開始する -- vi - 4-30 -
© Copyright 2025 Paperzz