OOM killer再び

前にOOM killerについて書いたときより、もう少し追い掛けなければいかんと思っていたので、深追い
まずはウェブから興味をひかれたネタを2つ

前者の記事にあるように危機的状況に陥ったときに乗客を機外に放り出すのが、OOM killerの動きではあるんだけど、実装を眺めるとそんなに出鱈目に乗客(あるいはパイロット)を選んでいるわけではなさそう。ただ、その実装も完全にあてになるわけではなくて、後者の記事ではNUMA環境下において殺してもメモリ飢餓状態を改善しない、ある意味無実のプロセスを殺して周るというkernelの動作が問題となっている。こちらのオチとしてはNUMA環境下ではOOM killerが動かないようにしましょうという事になったようだ。
で、通常のときの犠牲者探しの動作はどうなっているかというのが、linux/mm/oom_killer.cの中の実装。この中が呼ばれるときはシステム全体がメモリ飢餓状態に陥っているので、悠長に処理できない。何せメモリが無いから、作業用のメモリも贅沢には取れない、専用のconstrained_alloc()という関数があるぐらい。処理の流れとしては、out_of_memory()->select_bad_process()->badness()->oom_kill_process()、って感じ。
このうちbadness()が

  • CPU時間の消費具合
  • 子沢山具合(子供を一杯産んでいるほどbad)
  • nice値(低い優先度ほどbad)
  • ケーパビリティ(root権限があれば大幅免除)
  • ハードウェアへのアクセス状況(なんか重要そうなことをやっているので、やはり免除)

を元に殺してもよさそうなのを判定していく。実は、殺されたくないプロセスは明示的に示しておくことも可能で、/proc//oom_adjに"-17"を入れておくと無条件に探索対象から外される(なんとバッドノウハウな)。
これらの選択基準も前述にもある通りNUMAの環境においてはあまり有効に動かないようだが、通常の環境下ではそれなりに動くのではないだろうか。
以前、BSD Mag.で商用UNIXはこの種の挙動が安全側に設定してあるとあったけど、*BSDLinuxは大らかな環境で使われることの方が多いだろうし、まぁ、こんな挙動もあっていいのではないかと。