🐧 Linux 総合学習プラットフォーム
OS内部/起動の仕組み ・ 上級

仮想メモリの仕組み——ページとキャッシュ

動いているプロセスはそれぞれ、自分専用の広大なメモリ空間を見ているつもりでいますが、これは仮想アドレスというカーネルが見せている錯覚です。実際のメモリは4KiB程度のページという単位で物理メモリに対応付けられ、必要になった瞬間に割り当てるページフォルトという遅延戦略で無駄なく使われます。free コマンドが示す buff/cache は使用中に見えて実質は空きの仲間であり、この誤読は多くの初心者がつまずく落とし穴です。/proc/meminfo の主要な行まで読めるようになれば、メモリ不足の判断を数字で行えるようになります。

動いているプロセスはそれぞれ、自分専用の広大なメモリ空間を丸ごと使えているつもりでいる。だがこれは錯覚で、実際にはカーネルが用意した仮想アドレス空間を見ているにすぎない。

🔗
たとえ仮想アドレス空間は、住民ごとに配られる「同じ間取りの部屋番号表」のようなものだ。どの部屋も1号室から始まって見えるが、実際にどの建物のどこにあるかは、住民自身は知らないし気にしなくてよい。
💡
ポイント仮想アドレスと物理アドレスは別物だ。プログラムが扱うのは前者であり、実際にどの物理メモリへ対応するかはカーネルとハードウェア(MMU)が裏側で管理している。

この仕組みのおかげで、複数のプロセスが同じような番地を使っていても互いに干渉しないし、あるプロセスが暴走して変な番地へ書き込もうとしても、他のプロセスの領域を壊さずに済む。

🗺️ 仮想アドレス空間という個室

各プロセスは起動すると、0番地から始まるかのような自分専用のアドレス空間を割り当てられる。この変換作業を担うのがMMU(メモリ管理ユニット)というCPU内の仕組みで、カーネルが管理する変換表を参照しながら、仮想アドレスを実際の物理アドレスへ都度読み替えている。

この変換のおかげで、プログラムを書く側は「メモリは自分専用に広く使える」という単純な前提でコードを書ける。裏側の込み入った調整はカーネルに任せられる。

🧩 ページという単位

仮想アドレスと物理アドレスの対応付けは、1バイトずつ細かく行うわけではない。ページと呼ばれる一定サイズ(多くの環境で4KiB)の塊を単位として、まとめて管理される。

プロセスA(仮想)page 0page 1プロセスB(仮想)page 0page 1MMUが変換物理メモリ(同じ番地表記でも実体はバラバラ)同じ「page 0」でも指す先は別のフレーム

⏳ ページフォルトと遅延割り当て

プロセスがメモリを要求した瞬間に、カーネルがすぐ物理メモリを割り当てるとは限らない。実際に読み書きが発生するまで割り当てを先延ばしにするデマンドページングという戦略が広く使われている。

プロセスが「まだ物理メモリと対応付けられていないページ」へアクセスすると、CPUはページフォルトという例外を発生させる。カーネルはこれを検知し、そこで初めて物理メモリを割り当てて対応付ける。

つまずきページフォルトという言葉には「障害」のような響きがあるが、この種のフォルトは異常ではなく、仮想メモリの正常な動作の一部だ。大量に頻発して性能が悪化する状態と区別して捉えるとよい。

この遅延戦略のおかげで、プログラムが「確保しただけで実際には使わない」メモリ領域に対して、無駄に物理メモリを消費せずに済む。使う分だけ、使うタイミングで実体が割り当てられる。

💾 free コマンドで見るメモリ

実際にメモリの使用状況を見るには free コマンドを使う。ただし出力の読み方には落とし穴があり、buff/cache の列を「使用中で危険な状態」と誤解する初心者は多い。

$ free -h total used free shared buff/cache available Mem: 7.6Gi 1.2Gi 3.1Gi 120Mi 3.3Gi 6.0Gi Swap: 2.0Gi 0B 2.0Gi buff/cache はディスクの内容を一時的にメモリへ写した部分で、必要になれば即座に解放して他の用途へ回せる。実質的には「空き」の仲間だと考えるのが実態に近い。
total(物理メモリ全体)used(実使用中)buff/cache(すぐ解放可)free(未使用)available ≈ free + buff/cacheの再利用可能分
コツavailable の列は、buff/cache の再利用可能な分もあらかじめ加味した「実質的にすぐ使える量」を示している。空き容量の逼迫具合を見るなら、free の値よりも available の値を優先して見るとよい。

🔄 スワップという逃がし先

物理メモリが足りなくなってきたとき、カーネルは使用頻度の低いページを一時的にディスク上のスワップ領域へ退避させ、物理メモリを他の用途へ回す。これがスワップだ。

つまずきスワップが少し使われる程度なら正常な範囲だが、頻繁に読み書きが発生している場合は、物理メモリ不足のサインだ。ディスクはメモリよりずっと遅いため、スワップの多用は体感速度の低下に直結する。

📄 /proc/meminfo で詳しく見る

free の集計元をさらに細かく見たいときは /proc/meminfo を直接読む。free コマンドが表示する各値は、実はこのファイルの数字を要約したものにすぎない。

$ cat /proc/meminfo MemTotal: 7969800 kB MemFree: 3255600 kB MemAvailable: 6291200 kB Buffers: 182400 kB Cached: 3012800 kB SwapTotal: 2097148 kB SwapFree: 2097148 kB
MemTotalMemFreeBuffersCachedMemAvailable ≈ Free+再利用可能分スワップ領域SwapTotalSwapFree物理メモリ不足時の退避先

MemTotal は物理メモリの総量、MemFree は本当に何も使っていない量、MemAvailable は buff/cache の再利用可能分まで含めた実質的な空き量にあたる。Buffers はブロックデバイスの入出力用、Cached はファイル内容のキャッシュで、どちらも free コマンドの buff/cache に合算されている。

仮想メモリという抽象化は、プロセスを互いに守りながら、限られた物理メモリを使い回すための土台になっている。次はこの土台の上に、プロセスの世界そのものを分けたり絞ったりする namespace と cgroups を見ていく。

この項目に出てくる用語

仮想アドレス空間かそうあどれすくうかん
各プロセスに割り当てられる、自分専用に見えるメモリ番地の集合。
ページフォルトぺーじふぉると
まだ物理メモリと対応付けられていないページへアクセスした際にCPUが発生させる例外。
デマンドページングでまんどぺーじんぐ
メモリを要求された時点ではなく、実際に使われる瞬間まで物理メモリの割り当てを遅らせる戦略。

関連コマンド

free

▶ 学習アプリでこの続きを学ぶ・演習する