レベル: 初級 秋田 英行, 日本アイ・ビー・エム
2007年 04月 27日 PDを行う際に心強い味方となってくれるのがさまざまなツール類です。ツールを利用することで、ログや設定ファイルからだけでは分からない、システムの内部情報についても知ることができます。そこで今回は、過負荷状態となったときOSの内部ではどのような動作が行われているのか、幾つかのツールを使用して探ってみましょう。
ツールを使いこなすべし
OS上でPD*を進めるにあたり、「設定ファイルやログファイルの確認は当然すべきである」ということはすでに述べてきました。いまさら言うまでもないことですが、設定ファイルは「対象となる機能の動作をパラメータで定義した静的な情報」であり、ログファイルは「OSやソフトウェアが発行するメッセージを記録したもの」です。しかし、システム上で発生し得る現象を、これらの情報だけですべて把握することはとうてい不可能です。そこで、さまざまなツールを適材適所で使いこなし、得られる情報を的確に分析することが必要となります。
PDで利用するツール
Linuxにおいて、PDで利用可能なツールは通常ディストリビューションのパッケージという形で入手できます。はじめに、どのようなツールがPDに利用できるかを整理してみましょう。表1は、Red Hat Enterprise LinuxでPDに利用できるツール類です。また、表2は、別途インストールなどが必要であるものの、有用なツール類になります。ここでは主なツールのみ挙げていますが、このほかにも通常何げなく使っているツールや機能などで、PDに役立てられるものは多くあるでしょう。今回はこれらの中でも使用頻度の高いvmstat、iostat、topをピックアップし、その使用方法やPDにおけるポイントなどを順に述べていきたいと思います。
図1. PDに利用可能なツール(Red Hat Enterprise Linuxのパッケージとして収録されているもの)
表2 PDに利用可能なツール(別途インストールやパッチの適用が必要なもの)
パフォーマンス劣化問題をシミュレートする
さて、今回はPDにおけるツールの利用方法を理解してもらうため、簡単なシミュレーションを行ってみたいと思います。このシミュレーションで「CPUとメモリに負荷をかけた場合にシステムはどのような挙動を起こすのか」ということを体験していただきましょう。
まず、CPUおよびメモリに負荷をかけるツールを用意します。CPUとメモリに負荷がかかればどのようなものでも良いのですが、今回はリスト1のような、簡単な自作サンプルプログラムを使用しました。
リスト1 サンプルプログラム「swaptest.c」。太字部分については、実行例3で提示
#include <stdio.h>
#define BUF_SIZE (1024 * 1024)
#define MAX_INDEX 10
#define MAX_COUNT 10
main(int argc, char *argv[])
{
int pid, id;
char *tbl[MAX_INDEX];
int count = 0;
int i;
if(argc > 1)
count = atoi(argv[1]);
if(count <= 0)
count = MAX_COUNT;
for(id = 0; id < count; id++)
{
if ((pid=fork()) == -1)
exit(1);
if (pid == 0)
break;
printf("%02d: pid=%d\n", id, pid);
}
pid = getpid();
for(i = 0; i < MAX_INDEX; i++ )
{
tbl[i] = (char *)malloc(BUF_SIZE);
}
while(1)
{
for(i = 0; i < MAX_INDEX; i++)
{
bzero(tbl[i], BUF_SIZE-1);
}
printf("%02d: pid=%d, i=%d\n", id, pid, i);
sleep(2);
}
}
|
このプログラムは、引数で指定された数だけの子プロセスを生成し、自身と各子プロセスが大きさBUF_SIZEのメモリ領域をMAX_INDEX回割り当てて、そのメモリ領域にゼロを入れる、といった処理を繰り返すプログラムです。この例ではBUF_SIZEが1Mバイト、MAX_INDEXが10であるため、コマンドの引数に20を渡すと親プロセスと20個の子プロセス、計21個のプロセスがそれぞれ10Mバイト、合計で210Mバイトのメモリを配列として確保し、強制終了させるまでその配列にゼロを埋める処理を行ってCPUを消費し続ける、という動作を行います。このプログラムを次のようにコンパイルし、swaptestを作成します。
$ gcc -o swaptest swaptest.c
|
また、このプログラムの実行に当たってシステムの挙動を分かりやすくするため、システム全体で使用するメモリサイズを256Mバイトに、CPU数を1に指定しました。これはLinux起動時に「mem=256M」と「maxcpus=1」をカーネルパラメータとして与えれば済みます。
プログラムの実行
さて、それではこのプログラムを実行してみましょう。今回はswaptestプログラムを2つ、段階的に実行することでシステムの挙動の変化を観察します。与える引数は環境によって異なると思いますが、今回の例では引数を12とすると、コンソール入力やsshセッションに体感できるほどの遅延が発生しました。
さて、この「遅延」という現象は、実際には何が原因で発生しているのでしょうか? さっそく、PDを行ってみます。
コンソールの遅延問題をPDする
PDの手順としては、既に解説したとおり、
- 状況把握
- 情報収集
- データ分析
- 解決を図る
というのが一般的です。それらを踏まえ、今回のシミュレーションを行っていきましょう。
ステップ1 構成情報の確認
PDに必要な構成情報を実行例1のように取得します。このシミュレーションのテーマは「プログラムによる負荷がシステムに与える影響の観察」であるため、詳細なハードウェアの構成情報などは取得していません。
実行例1 システム構成情報の取得
# cat /proc/cpuinfo ←CPU情報の取得
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 8
model name : Pentium III (Coppermine)
stepping : 6
cpu MHz : 797.542
cache size : 256 KB
:
:
# head -n 5 /proc/meminfo ←メモリ情報の取得
total: used: free: shared: buffers: cached:
Mem: 260218880 26763264 233455616 0 1916928 11431936
Swap: 4293586944 15331328 4278255616
MemTotal: 254120 KB
MemFree: 227984 KB
# fdisk -l ←HDDパーティション情報の取得
Disk /dev/sda: 36.4 GB, 36401479680 bytes
255 heads, 63 sectors/track, 4425 cylinders
Units = シリンダ数 of 16065 * 512 = 8225280 bytes
デバイス ブート 始点 終点 ブロック ID システム
/dev/sda1 * 1 13 104391 83 Linux
/dev/sda2 14 535 4192965 82 Linux スワップ
/dev/sda3 536 3146 20972857+ 83 Linux
|
ステップ2 データの取得
次にシステムの稼働情報を取得するわけですが、プログラムの実行によってシステムの動作が不安定になることは分かっているため、投入前と後のデータを取得して比較を行うことにします。取得するデータは仮想メモリ状況、I/O状況、プロセスの使用状況の3つ。これらの取得は、実行例2のように行います。
実行例2 仮想メモリ、I/O、プロセスの稼働状況を取得
# vmstat 1 >> vmstat.log & ←1秒間隔で仮想メモリ使用状況をログに記録
# iostat -x -t 1 >> iostat.log & ←1秒間隔でI/O状況をログに記録
# (while true; do top -b -n 1 >> top.log; sleep 1; done) & ←topを1秒間隔で実行し、プロセスの稼働状況をログに記録
|
準備が整ったら、実行例3のようにプログラムを実行します。これで現象発生中のデータが取得できるはずです。
実行例3 シミュレーション実施
# ./swaptest 12 &
: ← リスト1中で太字で示したprintfが実行されたら、再度swaptestを実行
# ./swaptest 12 &
:
:
# killall swaptest ←問題の現象が確認されたらkillallで停止させる
|
さて、ここまでで現象発生中のデータが取得できました。次回では、このデータを使い、ステータスの解釈やデータ分析方法に足を踏み入れていきましょう。
このページもしくは表内で出てきた専門用語
- PD
- Problem Determinationの略。直訳すれば、「問題を確定する」などになります。問題の切り分けをし、問題部分を特定する、つまり問題判別することをPDと呼びます。
- mkexec
- 現在起動中のカーネルから直接新しいカーネルを起動する仕組み。同様の機能にkexecがありますが、mkexecでは先に起動されていたカーネルのメモリ空間を上書きせず、任意のアドレスにダンプ用のミニカーネルをロードできるよう改良されています。
- /proc/sys
- このディレクトリ以下の仮想ファイルにアクセスすることで、システムの稼働情報を取得できます。
- リングバッファ
- カーネルがメッセージを記録するために使用するメモリ領域のこと。
- NIC
- Network Interface Card。
- 共有メモリ、セマフォ、メッセージキュー
- プロセス間で情報を共有したり、通信し合うための仕組み。
- slabキャッシュ
- カーネルの内部で頻繁に利用されるオブジェクト用のキャッシュ。
- アドレスマップ情報
- 仮想メモリが物理メモリやスワップデバイスにどのようにマッピングされているかを示す情報。
- クラッシュダンプ
- カーネルがクラッシュした際に使用していたメモリの内容を出力したもの。
参考文献
著者について  | |  | 秋田英行(日本アイ・ビー・エム) |
記事の評価
|