前回は,プロセスが利用するメモリーをLinuxがどのように管理するかを説明しました。Linuxでは,ページングという仕組みに基づいた仮想記憶機構を利用して,プロセスごとに実際のメモリー空間とは別の仮想メモリー空間を準備します。この仮想メモリー空間は,プロセス・スケジューラによって実行が切り替わるたびに切り替えられます。このような仕組みを採ることで,複数のプロセスで競合を起こさず,できるだけ効率的にメモリーを使えます。

 ところで,メモリーを利用するのはプロセスだけではありません。カーネル自身もメモリーを使いますが,その利用方法はプロセスの場合とは異なっています。また,物理メモリー・アドレスと仮想メモリー・アドレスの変換を行うのはプロセッサ(MMU)の仕事ですが,実際にその変換表(ページ・テーブル)を用意するのはカーネルの役割です。空き物理ページのうちどのページを割り当てるのか判断するのもカーネルです。

 そこで今回は,カーネルを中心にしてメモリー管理の仕組みを紹介します。

プロセスのメモリー空間の1Gバイトはカーネルが利用

 IA-32プロセッサは,32ビットのメモリー・アドレスを持ちますので,4Gバイトのメモリー空間を利用できます。これは,仮想メモリー空間でも物理メモリー空間でも同じです。そのため,仮想記憶を有効にしている場合は,4Gバイトの物理メモリーを搭載していなくても,4Gバイトの仮想メモリー空間をすべて利用できます。

 Linuxでは,プロセスごとに仮想メモリー空間を割り当てますので,各プロセスでは4Gバイトのメモリー空間を利用できるはずです。しかし実際にプロセスが(ユーザー・モードで)利用できるのは,先頭から3Gバイト(0x00000000~0xbfffffff)に制限されます。これは,残りの1Gバイト(0xc0000000~0xffffffff)をカーネルが(カーネル・モードで)利用するためです。

 プロセスが利用する先頭から3Gバイトの領域をプロセス仮想空間と呼び,残りの1Gバイトの領域をカーネル仮想空間と呼びます(図1)。これらは同じ仮想メモリー空間に存在しますが,別の仮想空間と考えても良いほど,用途や働きが異なります。

図1●プロセス仮想空間とカーネル仮想空間
図1●プロセス仮想空間とカーネル仮想空間
4Gバイトの仮想メモリー空間のうち,上位1Gバイトはカーネルが利用するカーネル仮想空間になっています。

 この両者は同一の仮想メモリー空間にマッピングされていますが,カーネル仮想空間はプロセッサの保護機構で保護されていて,ユーザー・モードで動作する通常のプロセスからはアクセスできません。カーネルが利用するメモリー領域にアクセスすると,メモリー保護違反が発生してエラーとなってしまいます。システム・コールの実行などで,カーネル・モードに移行したときに初めてこれらの領域にアクセスできます。

 また,プロセスが異なると仮想メモリー空間も異なりますが,カーネル仮想空間の部分については全プロセスで共用し,同一の内容になる点も大きな違いです。あるプロセスの処理によりカーネル仮想空間に変更が生じた場合,その変更は(途中でカーネルに変更されない限り)他の全プロセスに波及します。

 なぜ,このようにしているのでしょうか。メモリー空間を分離するという仮想メモリーの考え方からすると,カーネルにも専用の仮想メモリー空間を割り当てて,プロセスが仮想メモリー空間全体を利用できるようにした方が良いように思えます。