0.6 メモリ管理

 Linuxカーネルは、2種類のメモリ管理を行っています。1つは実メモリ管理と呼んでいるもので、実際にシステムに組み込まれたRAMチップ内のメモリ領域(実メモリ)を管理します。もう1つは仮想記憶と呼ばれているものです。アプリケーションから参照するメモリアドレスは、実メモリのアドレスではなく、仮想空間と呼ばれる仮想的な領域におけるアドレスとなっています。この仮想空間の概念を取り込んだことによって、非常に柔軟なメモリ管理を行えるようになっています。

 従来のUNIXでは、高価で容量が少ない実メモリを効率的に管理することを前提にメモリ管理機構が実装されてきました。しかし、近年の実メモリの大容量化とキャッシュメモリとのアクセス速度差の拡大により、伝統UNIXが行ってきた手法では非効率になりつつあります。将来のLinuxカーネルでは、このメモリ管理機能が大きく書き直される可能性を秘めています。

 本書のPart 3のトピックです。

0.6.1 実メモリ管理

 Linuxカーネルは実メモリをページという単位で管理しています。ページは、仮想記憶機構を利用したときにCPUがサポートするメモリ管理の最小単位です。つまりページの大きさは、CPUの種類ごとに異なることになります。

 Linuxカーネルは、ページ単位での実メモリの空き領域を効率的に管理するための仕組みとして、Buddyシステムと呼ばれる管理方式を導入しています。Buddyシステムは、隣り合った空き領域を結合し、より大きな空き領域を作り出そうとします。

 また、Linuxカーネルはしばしば、小さなメモリ領域を必要とします。これらページより小さなメモリ領域を効率的に管理するための方式として、Slabアロケータと呼ばれるメモリ管理方式も備えています。Slabアロケータは、フラグメントの発生を最小限に抑えることと、メモリキャッシュ利用効率を考慮したメモリ管理方式です。

 「第11章 実メモリの管理」、「第12章 動的メモリ割り当て」にて、これらの話題を扱います。

0.6.2 仮想記憶

 仮想空間の機能によって、物理的に分散したページを集めて、連続した仮想空間に割り付けることができます。つまり、実メモリの断片化問題を考慮する必要がなくなります。

 Linuxカーネルは、各プロセスに独立したアドレス空間を割り当てています。これを多重仮想空間と呼びます(図0-5)。各プロセスは広大なアドレス空間(プロセス空間)に、プログラムを割り付けて実行します。ほかのプロセスと競合することがないため、自由にアドレス空間を利用できます。プロセス空間には、テキスト、データ、ヒープ、スタック域などが割り当てられます。テキストを配置した領域は、アプリケーションの障害で破壊することのないように、書き込み保護も持たせています。この仮想空間を造るための基本機能については、「第9章 アドレス変換機構」で説明します。

0.6.2.1 デマンドページング

 Linuxカーネルはページング機構を提供していますが、プロセス空間すべてに実メモリを割り当てるわけではなく、参照が発生した領域に対して、ページ単位で実メモリを割り当てていきます。これはデマンドページングと呼ばれている機構です。また、参照頻度の低い領域に割り付けられた実メモリは、スワップ機構によってシステムへ返却され、ほかの利用頻度の高い領域用に再割り当てされます。さらに、コピーオンライトと呼ばれる、実際に書き込みが発生するまで親プロセスと子プロセスの間でページを共有させるための仕組みも備えています。プロセスのforkは頻繁に行われますが、この仕組みによって、fork時に行われるプロセス空間の複製処理を高速化します。これらページング機構は、Linuxカーネル上で動作しているプロセスには透過的であり、裏でこのような処理が動作していることを意識することはありません。

 「第13章 プロセス空間の管理」にて、詳しく説明します。

0.6.2.2 ページアウトとスワップ

 Linuxカーネルではページを二次記憶に追い出すことをスワップと呼んでいますが、伝統UNIXで行っているプロセスイメージ全体を追い出すスワップアウトではなく、ページ単位で追い出すページアウトのことを指しています。Linuxでは伝統UNIXのスワップアウト機能に相当する機構は実装されていません。メモリの大容量化に伴い、その必要性が薄れてきたためと考えられます。

 この動きは、Linuxカーネルの中でも正確な理解が難しい個所の1つです。「第14章 ページの回収処理」で、解説します。