物理メモリ不足について考えよう
仮想メモリ機能のおかげで、ユーザープロセスは物理メモリの量を気にせずにメモリを確保します。大事なことなのでもう1回説明しますが、各ユーザープロセスが確保した仮想メモリは、最初からすべて物理メモリを割り当てられているわけではなく、実際にメモリにアクセスしたときに割り当てられます。実際に使うか使わないか分からないメモリに対しては、物理メモリは割り当てません。
こうして、物理メモリはある程度節約しながら大事に使用されていきますが、システム構築前に行う物理メモリ搭載量設計がうまくいっていないと、すぐに物理メモリ使用量が物理メモリ搭載量を上回ってしまいます。これが「物理メモリ不足」です。
物理メモリはユーザープロセスとカーネルが共通して利用している資源です。物理メモリ不足はOS全体の存亡にかかわりますので、カーネルはさまざまな手段で物理メモリ不足に対抗します。代表的な3つの物理メモリ不足回避手段を挙げてみます。
1. swap(スワップ)
非常に有名な機能です。物理メモリが足りなくなった場合に、HDD上に確保したswap領域に一時的にメモリの内容を退避させることで、空き物理メモリを確保します。スワップアウトした領域はRSSから削られ、見えなくなります(注7)。
スワップアウトするための前提条件として、以下の2つを満たしている必要があります。
- ユーザー空間のメモリであること
- 無名ページ(注8)か共有メモリであること
2. ページキャッシュ回収
カーネルが最近利用していないページキャッシュを回収することで、物理メモリを確保します。最近利用していなくて、かつストレージと同期が取れていないページキャッシュについては、明示的に書き出して、ストレージとの同期が完了してから回収します。ページキャッシュについては第1回を参照してください。
関連記事:
第1回「減り続けるメモリ残量! 果たしてその原因は!?」
http://www.atmarkit.co.jp/flinux/rensai/tantei01/bangai01a.html
Linux Kernel Watch 番外編「Linuxメモリ管理の最先端を探る」
http://www.atmarkit.co.jp/flinux/rensai/watch2008/watchmema.html
3. OOM-Killer
swap領域に退避できない領域が多く、ページキャッシュの回収も間に合わない場合、メモリを多く利用しているプロセスをkillして、カーネルの動作に必要なメモリを確保します。この、いわば最終手段ともいえる機能が、悪名高いOOM-Killerです。OOM-Killerは物理メモリ枯渇を起因として発動しますが、実際にkillされるのは仮想メモリを多く確保しているプロセスです。そのため、仮想メモリを消費しているだけで、あまり物理メモリを使用していないような罪のないプログラムが殺される可能性もあります。このあたりが悪名高いゆえんですね。
物理メモリ不足時の最終手段はOOM-Killerです。たまに罪のないプログラムを殺してしまうことはあるとはいえ、いつかはメモリを確保し過ぎているプログラムを殺すこともできるでしょう。そのため、ユーザープロセスが原因でOSがハングアップするということは考えにくいことです。
関連記事:
Linux Kernel Watch 2006年3月版「カーネルが無実のプロセスをkillし始めるとき」
http://www.atmarkit.co.jp/flinux/rensai/watch2006/watch03b.html
Linux Kernel Watch 2008年2月版「OOM killerとの危険な関係に終止符は打てるか」
http://www.atmarkit.co.jp/flinux/rensai/watch2008/watch02a.html
それでは、物理メモリを浪費しているのがカーネルだったらどうでしょうか?
OOM-Killerはカーネルを殺すことはできません。そのため、カーネルの物理メモリ使用量が際限なく増えていくと、OOM-KIllerはユーザープロセスの中から仮想メモリを最も使用しているものを選び、killせざるを得ません。そうしてOOM-Killerは、仮想メモリ使用量の順に次々と罪のないユーザープロセスを殺していき、ついには、OSとして動作するための最低限のプロセスであるinitですら殺し、OSは停止してしまいます。ここからASRによってリブートしてしまうケースはありそうです。
注7:topのmanなどには「仮想メモリ使用量(VIRT)=スワップサイズ(SWAP)+物理メモリ使用量(RES)」との表記がありますが、Linuxに関してはこれは成り立ちません。Linuxではスワップアウトしたサイズをユーザープロセスごとに計算できませんし、スワップサイズ=0だとしても、仮想メモリ使用量=物理メモリ使用量とならないからです。
注8:ユーザープロセスがメモリ獲得関数(malloc、mmpaなど)で確保したり、プログラム本体用に利用するページを指します。
今回はどのメモリ不足の種類なのか
ここまで見てきた内容を一覧にしてみました(表4)。
ユーザー空間 | カーネル空間 | |
---|---|---|
仮想メモリ | カーネルへの影響:なし 他プログラムへの影響:なし 発生事象:メモリを消費したプログラムでENOMEMエラーが発生する |
カーネルへの影響:限定的 他プログラムへの影響:なし OSハングアップという観点では考慮不要 |
物理メモリ | カーネルへの影響:なし 他プログラムへの影響:あり 発生事象: ・スワップアウト発生 ・ページキャッシュ減少 ・OOM-Killer発生 |
カーネルへの影響:あり 他プログラムへの影響:あり 発生事象: ・スワップアウト発生 ・ページキャッシュ減少 ・OOM-Killer発生 |
表4 メモリ不足の分類と発生する事象 |
この中で、カーネルへの影響があり、OS停止に至り、リブートする可能性があるのは、「カーネル空間」の「物理メモリ」を消費しているときだということがいえそうです。
さあ、次回はいよいよカーネル内のどこで物理メモリを消費していたのか、事の真相に迫りましょう。
Copyright © ITmedia, Inc. All Rights Reserved.