Linux仮想アドレス空間管理

Linuxにおける仮想アドレスと物理アドレス

図1はLinuxにおける仮想アドレスと物理アドレスの関係を示しています。
図1:Linuxにおける仮想アドレスと物理アドレスの関係

Linuxの1つ1つのプロセスは互いに独立した仮想アドレス空間を持っています。 従って、仮想多重空間を作っていることになります。 一方カーネルは1つで、多重化されていません。プロセスから見ると、カーネル 空間は全く見えず、通常上限が3Gバイトの仮想空間に見えます。もちろん、他の プロセスの仮想空間も見えるははずがありません。しかし、カーネル空間からは ある時点でのプロセス空間の全てが見えてしまいます。カーネルは通常1Gバイトの 大きさの仮想空間を作り、さまざまのプロセスの仮想空間を見ることができます。

また物理アドレスとの関係で言えば、プロセス空間は仮想記憶システムの複雑な アドレス変換機構で管理されているのに対し、カーネル空間は物理アドレスに ストレートにマッピングされています。 下記にカーネルの仮想アドレス、物理アドレス、バスアドレスの関係を インテルのx86 CPUの場合について、示します。 /usr/src/linux/include/asm/io.hに下記のような関数が定義されています。

そして、それらの関数はまた次のように定義されています。
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
extern inline unsigned long virt_to_phys(volatile void * address)
{
        return __pa(address);
}
extern inline void * phys_to_virt(unsigned long address)
{
        return __va(address);
}

in /usr/src/linux/include/asm/page.h
#define __pa(x)                  ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x)                  ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define __PAGE_OFFSET            (0xC0000000)
#define PAGE_OFFSET              ((unsigned long)__PAGE_OFFSET)
これらの定義から、インテルx86 CPUにおいては になります。 参考のため、現在の物理アドレスがどのようになっているかを知るために /proc/iomemを見てください。
00000000-0009fbff : System RAM
000a0000-000bffff : Video RAM area
000c0000-000c7fff : Video ROM
000c8000-000cc7ff : Extension ROM
000f0000-000fffff : System ROM
00100000-07ffffff : System RAM
  00100000-0022f8d5 : Kernel code
  0022f8d6-002aa143 : Kernel data
f8000000-fbffffff : S3 Inc. ViRGE/DX or /GX
ffbeb000-ffbebfff : Adaptec AIC-7881U
ffbefc00-ffbefc7f : Digital Equipment Corporation DECchip 21140 [FasterNet]
  ffbefc00-ffbefc7f : eth0
fff80000-ffffffff : reserved

Linuxにおけるカーネル空間とプロセス空間

さて、図2は図1で示した関係を実際のプログラムで見て見ましょう。
図2:Linuxにおけるカーネル空間とプロセス空間

プロセス空間には図に示されたプログラムがあります。右手の方です。 このプログラムで定義されてdataの領域はスタック領域になります。 仮想アドレスではここでは0xBFFFF4BCです。プログラムはdataに 0x55555555を入れて、これをioctlシステムコールで/dev/skeletonという デバイス名のドライバに渡そうとしています。一方、カーネル空間上では そのデバイスドライバがskeleton_ioctlというメソッドで待ち構えています。 argという引数で受け取ることになっています。注目すべきはこのargが 抱えているアドレスが0xBFFFF4BCでプロセスの仮想アドレスと同じ値だ ということです。つまり、カーネルはプロセスの仮想アドレスをそのまま 扱うことが可能だということを示しています。