カーネルって偉い!

衝動買いから始まって32やら64bitやらPAEが
どぉちゃらなんてところまでいったので、カーネルの
最も基本であるプロセスやメモリ管理についても
少々書き残しておかなくては・・・って思っては
みたものの、拙生の持ち合わせる知識はLnuxのみで、
しかもホンのサワリだけになります。
(Windowsは・・・きっと間違えて覚えてる・・・
 というよりは・・・よく知りません。。。^^;; )

Linuxはマルチタスクで稼働するため、複数の
プロセスが同時に実行されます。

・ プロセスとは
 アクティブなプログラムとそれに使用される
 リソースの総称を言います。

最近のCPUはマルチコアが主流で、2コア4スレッドだの
4コア8スレッドといった1パーケージに複数のCPUが
存在していたり、サーバーなどではそれらのCPUを
更に複数で使うことは珍しくありません。
* 以降CPUコアとかスレッドなども含めCPUと表記します。
しかしそれらの数はしれており、それを上回るプロセスが
実行されるときは、1CPUを複数ののプロセスが共有しなくては
いけません。
残念なことにCPUが1度に処理できるプロセスは1個だけで
同時に複数のプロセスを実行することはできません。

実際に複数のプロセスを実行させることは多々あります。
それはカーネルが行うプロセス管理によって実現します。

プロセス管理

カーネルは
・タスクスケジューラという機能を使って、
・短時間に複数のプロセスを切り替えながら
・CPUに実行させることで、
・まるで同時に実行しているように見せかける
・・・というある意味姑息な(笑)方法で処理します。
実際には疲れ知らずのコンテキストスイッチが献身的に
切り替え処理を行ってくれることでLinuxのマルチタスク
は実現されています。

いくつかのスケジューラーがありますが、Linuxは
Completely Fair Schedulerが標準です。
レッドブラックツリー(赤黒木)というアルゴリズムを
使っていますが、基本的には使用時間が短いプロセスに
プライオリティを持たせて公平を保つ仕組みです。

メモリ管理

プロセスの実行時はデータなどをメモリにロードしますが
1CPUがタスクスケジューラーで複数プロセスを処理していても、
同じアドレスを参照したりアクセスしないように、各プロセスに
独立した領域を確保するためのメモリー管理はカーネルの
最も重要な機能の1つであります。
ただし意図的に共有する場合もあります。

Linuxのメモリについて

(mmapやbrk等の説明は割愛し、ごく抽象的に・・・
    ってそっちのほうが難しいかも・・・です。)
メモリは【ページ】という単位で管理されます。
カーネルはページサイズである4KBを単位として
プロセスにページを割り当てています。

デマンドページング

メモリが必要になったぜ、というプロセスの要求に
カーネルは新たな仮想アドレスを割り当てます。
(RSSやVSZも割愛しごく抽象的に・・・)
じつはこの時点で予定領域を割り振っただけであり、
実際のページを割り当てたわけではないのです。
プロセスがアクセスしてきて初めてページ(メモリ)を
割り当てることになります。
これを【ディマンドページング】と言います。

言い換えると、実行中のプログラムが使用している
仮想ページ分だけを実メモリにロードし、リソースの
節約を行うということになります。

メモリー不足時の処理

・スワップ
Linuxでは通常ハードディディスクなどにSWAP領域を設け、
実メモリが不足した時に、アクセス頻度の低い領域を
SWAP領域に書き出すスワップアウトを実行します。
スワップアウトされた領域にアクセスがあると、反対に
実メモリに引き戻すスワップインを実行します。
当然HDDの速度はメモリと比較すると格段に遅いので、
スワップが発生する場合処理速度が低下してしまいます。

・アウト・オブ・メモリ・キラー
SWAP領域が満杯で使えないとかSWAP領域を持たないシステムで
実メモリが不足した場合、カーネルは最終手段を行使します。
実行されてから長時間が経過していて、なおかつ必要な
メモリ領域を確保できるプロセスを強制終了させて、新たに
実行させるプロセスに必要な実メモリの領域を確保し割り当てます。

いずれにしてもスワップやアウトオブメモリキラーが
発生する頻度が高い場合は、根本的に実メモリー不足そのもの
なので、システム自体のの見直しが必要ということです。

SWAP領域および使用量は
$ cat /proc/meminfo
で確認することができます。

MemTotal: 16552040 kB
MemFree: 13270320 kB
Buffers: 209992 kB
Cached: 1430776 kB
SwapCached: 0 kB
—– 中略 ———-
SwapTotal: 12467228 kB
SwapFree: 12467228 kB
Dirty: 348 kB
—– 以降省略 ———-

実メモリ16GB、SWAP領域はインストール時ubuntuが
自動で割り振った12GB程度ですが、上記例ではスワップは
全く発生していませんね。

ちなみに略さずに載せたものにつてちょっと。。。

Cachedが1.4GB程度となっています。
プロセスがHDDにデータを書き込む場合、HDDより速度の早い
メモリに可能な限りキャッシュし、あとからゆっくりHDDに書き込みます。
プロセスはキャッシュされた時点でHDDに書き込んだぞぉと
返されるので騙されてしまい、実際のHDDへの書き込みを
待つことなく次の作業を開始するわけです。
逆にディスクから読み込んだときは、やはりそのデータを
可能な限りメモリにキャッシュしておきます。
同じデータへのアクセスにはHDDではなくキャッシュ内から
返すので、非常に高速となります。

Dirty (実際に汚れているわけではありません・・・)

ファイルシステムに書き戻す必要のあるデータを
有するページをDirty pageと言い、書き戻すまでは
破棄できません。

↑よく見かける説明なのですがわかりますか?
拙生が初めて見た時はチンプンカンプンでありました。。。
要はページキャッシュに書き込まれただけで、まだ
ディスクには書き込まれていない、つまり未処理状態の
ページをDirty pageと言います。
ディスクからキャッシュ上に読み出されて未処理の場合も
Dirty pageです。。。(そのはず。。。)
設定した容量のリミット超えると、パフォーマンスに影響すると
聞いたことがあります。。
meminfoを実行するたびに数値がコロコ変わりますが、
このパソで見る限り0〜340KB程度となっていますが
比較的暇なサーバーで見ると0〜20MB位で、数MBが
頻繁に出ては消え出ては消え・・・です。
(コロコロ変わる数値ですが必ず4の倍数です。)

ふぃ〜、頭の中では理解しているつもりでも、書いてみると
けっこうあやふやだったり、表現することが難しかったり。。。
疲れたぁ〜。。。。

*カーネルのメモリ管理を語るには20項目くらい、
 分厚い本が1冊できるほどになるでしょうか。
 さらに面白い新技術などもどんどん加わり、
 ご紹介したいことはいろいろあるのですが、
 例えば・・・
 自動バランス機能によるNUMAマシーンの高速化
 について語るには、まずNUMAとは・・・
 メモリアロケータ・・・複数ノード化・・・
 なんて前ぶり説明から入らないといけません。
 (NUMA自体は特殊なアーキテクチャで、純粋に技術的な
  興味だけで、拙生の環境では必須ではありません。)
 
 極力噛み砕いて書こうとしていますが、省略・簡略化って
 全部書くより難しいです。
 また疑問に思っていることなどは知ったかぶりせずに
 そのまま素直に疑問として残してゆきます。
  

 このポストは7日夜に下書きしてあったものです。

HOME

おすすめ