【OOM Killer】知っ得!Linux Kernel の Tips

BeagleBoneBlackを買いました。手のひらサイズでUbuntuが動くのはすごいですね。
今回は主にlinuxサーバ管理とかで知っておくと役に立つかもしれない, Linux KernelのTIPSです。

debian_logo

便利!疑似デバイス

デバイスファイルには基本的には, H/Wが対で存在しますが Linux(Unix系)にはH/Wがない疑似デバイスが存在します。
これらを効果的に使うことで, システム管理が簡単になるかもしれません。

/dev/null はデータサイズ 0(EOF)を返す, 特殊デバイスファイルです。
大量の書き込みデータを無視したいときや, 標準出力/標準エラーを破棄したいときに使います。

$ command  > /dev/null 2>&1

2>&1ですが, stdinは0, stdoutは1, stderrは2を意味します。この場合, 標準エラーを吐き出さないように標準出力にまとめています。

/dev/fullは書き込み上限のエラーを返すデバイスファイルです。
ファイル出力を行うプログラムのデバッグで使います。

$ .a.out  > /dev/full

/dev/zeroは常に0を出力するデバイスファイルです。例えば、HDDを消去する時などに使えます。

$ dd if=/dev/zero of=hddimage ds=512G count=1

静かな殺し屋。OOM Killer

Linux Kernelは物理メモリが足りなくなるとスワップアウトでHDDにメモリを退避させます。
しかし, スワップアウトが増大するとカーネル自体の動作に支障が生まれてきます。

この時に OOM Killer (out of memory killer)と呼ばれる機能で, 稼動中のプロセスを停止させて空きメモリを増やします。

ただし, むやみにプロセスを終了させてしまっては困ります。必要なデーモンプロセスでさえ止めてしまうかもしれません。

Linux Kernel 2.6.36 以降では主に以下のルールで止めるプロセスを決めています。

  • 親プロセスは終了させない。異なるメモリ空間にある子プロセスで消費メモリが大きいプロセスから終了させる。
  • memory cgroupにあるプロセスは対象外とする
  • oom_score_adjに-1000を設定しているプロセスは対象外とする
  • 管理者権限より一般ユーザ権限のプロセスが優先的に終了させる

上記ルールに基づくと, あるPIDのプロセスを対象外にするには,

$ echo -100 /proc/[PID]/oom_score_adj

とすれば OK です。

メモリ/CPU統計情報

/proc/meminfo でメモリ使用情報を取得できます。free(1)はこの情報を整形しています。

$ cat /proc/meminfo
MemTotal:        1034596 kB
MemFree:          315540 kB
Buffers:           53400 kB
Cached:           344636 kB
SwapCached:            0 kB
Active:           404756 kB

man procの説明は以下になっています。

MemTotal %lu : 使用可能な RAM の総量
MemFree %lu : LowFree+HighFree の合計値。
Buffers %lu : Relatively temporary storage for raw disk blocks that shouldn’t get tremendously large (20MB or so).
Cached %lu : ディスクから読み出したファイルのインメモリキャッシュ (ページキャッシュ)。 SwapCached は含まれない。
SwapCached %lu : 一度スワップアウトされ、その後スワップインされたが、まだスワップファイルにも存在するメモリ。
Active %lu : 最近使用されたメモリで、通常は本当に必要にならない限り回収されないメモリ。
Inactive %lu : 最近あまり使用されていないメモリ。 他の使用するために優先して回収すべきメモリ。

続いて, CPUの統計情報です。top(1)はこの情報を使っているようです。

$ cat /proc/stat
cpu  2792 1106 1133 530117 922 0 110 0 0 0
cpu0 2792 1106 1133 530117 922 0 110 0 0 0
intr 94899 33 1127 0 0 0 0 0 0 0 0 11165 20869 152 0 0 203 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 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 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 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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

man proc によると各々の情報は以下で USER_HZ(1/100s)という単位のようです。

user (1) ユーザーモードで消費した時間。
nice (2) 低い優先度 (nice) のユーザーモードで消費した時間。
system (3) システムモードで消費した時間。
idle (4) タスク待ち (idle task) で消費した時間。
iowait (Linux 2.5.41 以降) (5) I/O の完了待ちの時間。
irq (Linux 2.6.0-test4 以降) (6) 割り込みの処理に使った時間。
softirq (Linux 2.6.0-test4 以降) (7) ソフト割り込みの処理に使った時間。
steal (Linux 2.6.11 以降) (8) 盗まれた時間 (stolen time)。仮想化環境での動作時に他のオペレーティングシステムにより消費された時間。
guest (Linux 2.6.24 以降) (9) Linux カーネルの制御下のゲストオペレーティングシステムの仮想 CPU の 実行に消費された時間。
guest_nice (Linux 2.6.33 以降) (10) nice が適用されたゲスト (Linux カーネルの制御下のゲストオペレーティングシステムの仮想 CPU) の 実行に消費された時間。

intrは起動後に処理された割り込み回数です。最初の値が合計値です。

sar(1)は秒間隔と回数を指定して, CPUが使用した情報を表示してくれます。

$ sudo apt-get install sysstat
$ sar 1 3
Linux 3.2.0-4-486 (debian)     2014年05月08日     _i686_    (1 CPU)

19時19分50秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
19時19分51秒     all      3.00      0.00      0.00      0.00      0.00     97.00
19時19分52秒     all      3.00      0.00      0.00      0.00      0.00     97.00
19時19分53秒     all      3.00      0.00      0.00      0.00      0.00     97.00
平均値:      all      3.00      0.00      0.00      0.00      0.00     97.00

また, メモリも同時に確認したいときは vmstat(8) はメモリとCPUの情報をまとめて表示してくれるので便利です。