UVM(9)

名称
UVM 仮想メモリシステム - 利用者向けインタフェース

書式
#include <sys/param.h> #include <vm/vm.h> #include <uvm/uvm.h>

解説
UVM 仮想メモリシステムは計算機のメモリ資源へのアクセス管理を行います。 ユーザプロセスやカーネルからこれら資源へは、UVM の利用者インタフェースを 通してアクセスします。UVM の利用者インタフェースには、以下があります:

-   UVM サブシステムの初期化
-   仮想アドレス空間の管理
-   ページフォールトの解決
-   ファイルとデバイスのメモリマッピング
-   仮想メモリへの uio ベースの I/O 実行
-   仮想メモリの割当と解放
-   実メモリの割当と解放

これらサービスの提供に加えて、UVM はページデーモンとスワッパの 2 つの カーネルレベルプロセスを持っています。ページデーモンプロセスは実メモリが 不足するまではスリープしています。不足が発生すると、ページデーモンは 起こされます。起こされると、実メモリを走査して、最近使用されていない メモリをページアウトし、解放します。スワッパプロセスは、空き場所があれば、 スワップアウト状態の実行可能なプロセスをスワップインします。

加えて、いくつかその他の関数があります。

初期化

void uvm_init() void uvm_init_limits(struct proc *p) void uvm_setpagesize() void uvm_swap_init()

uvm_init() は、システムの起動時に、UVM システムのセットアップを行います。 コピーライトが表示された後です。大域状態、ページ、マップ、 カーネル仮想メモリ状態、アーキテクチャ依存の実メモリマップ、 カーネルメモリ割当機構、ページャ、無記名メモリサブシステムを 初期化し、 カーネルオブジェクトのページングを有効にします。

uvm_init_limits() は、識別子のプロセスの制限値を初期化します。これは、システム起動時に、 あらゆる他のプロセスが起動される前に、プロセス 0 に対して使用します。

uvm_setpagesize() は、uvmexp のメンバの、pagesize (アーキテクチャ依存のコードで 初期化されていない場合のみ)、pageshift, pagemask を初期化します。これは pmap_init(9) 呼び出しの初めのアーキテクチャ依存コードで呼び出されます。

uvm_swap_init() は、スワップサブシステムを初期化します。

仮想アドレス空間の管理

int uvm_map(vm_map_t map, vaddr_t *startp, vsize_t size, struct uvm_object *uobj, vaddr_t uoffset, uvm_flag_t flags) int uvm_map_pageable(vm_map_t map, vaddr_t start, vaddr_t end, boolean_t new_pageable) boolean_t uvm_map_checkprot(vm_map_t map, vaddr_t start, vaddr_t end, vm_prot_t protection) int uvm_map_protect(vm_map_t map, vaddr_t start, vaddr_t end, vm_prot_t new_prot, boolean_t set_max) int uvm_deallocate(vm_map_t map, vaddr_t start, vsize_t size) struct vmspace * uvmspace_alloc(vaddr_t min, vaddr_t max, int pageable) void uvmspace_exec(struct proc *p) struct vmspace * uvmspace_fork(struct vmspace *vm) void uvmspace_free(struct vmspace *vm1) void uvmspace_share(struct proc *p1, struct proc *p2) void uvmspace_unshare(struct proc *p)

uvm_map() は、 map マップ内に有効なマッピングを確立します。 map はアンロック状態でなければなりません。新しいマッピングは size のサイズで行われます。 size は PAGE_SIZE の倍数でなくてはなりません。 uobj と uoffset 引数は、4 種類の組合せがあります。 uobj が NULL で uoffset が UVM_UNKNOWN_OFFSET の場合、 uvm_map() はアーキテクチャ依存の PMAP_PREFER 関数を使いません。 uoffset がそれ以外の値の場合、その値は PMAP_PREFER のヒント値として使用されます。 uobj が NULL でなく、 uoffset が UVM_UNKNOWN_OFFSET の場合、 uvm_map() は仮想アドレス上にオフセット位置を見い出し、 startp に設定します。 uoffset がそれ以外の値の場合、このオフセットに対して通常のマッピングが行われます。 マップの開始アドレスは startp に設定されます。

uvm_map() へ渡される flags は通常 UVM_MAPFLAG(vm_prot_t prot, vm_prot_t maxprot, vm_inherit_t inh, int advice, int flags) マクロで作成されます。このマクロは以下の値を使用します。 prot と maxprot がとる値は:

    #define UVM_PROT_MASK   0x07    /* プロテクションマスク */
    #define UVM_PROT_NONE   0x00    /* プロテクションなし */
    #define UVM_PROT_ALL    0x07    /* 全て */
    #define UVM_PROT_READ   0x01    /* 読出 */
    #define UVM_PROT_WRITE  0x02    /* 書込 */
    #define UVM_PROT_EXEC   0x04    /* 実行 */
    #define UVM_PROT_R      0x01    /* 読出 */
    #define UVM_PROT_W      0x02    /* 書込 */
    #define UVM_PROT_RW     0x03    /* 読出と書込 */
    #define UVM_PROT_X      0x04    /* 実行 */
    #define UVM_PROT_RX     0x05    /* 読出と実行 */
    #define UVM_PROT_WX     0x06    /* 書込と実行 */
    #define UVM_PROT_RWX    0x07    /* 読出と書込と実行 */

inh がとる値は:

    #define UVM_INH_MASK    0x30    /* 引き継ぎマスク */
    #define UVM_INH_SHARE   0x00    /* "共用" */
    #define UVM_INH_COPY    0x10    /* "複製" */
    #define UVM_INH_NONE    0x20    /* "無操作" */
    #define UVM_INH_DONATE  0x30    /* "供与" << 使われていません */

advice がとる値は:

    #define UVM_ADV_NORMAL  0x0     /* '通常' */
    #define UVM_ADV_RANDOM  0x1     /* 'ランダム' */
    #define UVM_ADV_SEQUENTIAL 0x2  /* 'シーケンシャル' */
    #define UVM_ADV_MASK    0x7     /* マスク */

flags The values that がとる値は:

    #define UVM_FLAG_FIXED   0x010000 /* 空間を見つける */
    #define UVM_FLAG_OVERLAY 0x020000 /* オーバーレイを確立する */
    #define UVM_FLAG_NOMERGE 0x040000 /* マップエントリをマージしない */
    #define UVM_FLAG_COPYONW 0x080000 /* コピーオンライトフラグを設定する */
    #define UVM_FLAG_AMAPPAD 0x100000 /* bss 用:malloc() を減らすため、 */
                                      /* マップにパディングする */
    #define UVM_FLAG_TRYLOCK 0x200000 /* マップをロックできなければ */
                                      /* エラーにする */

UVM_MAPFLAG マクロの引数は論理和オペレータで組み合わせて使用できます。プロテクションの 組合せのチェック用に、いくつかマクロが用意してあります、例えば UVM_PROT_WX マクロです。加えて、フラグからビットを取り出すマクロもあります。 UVM_PROTECTION, UVM_INHERIT, UVM_MAXPROTECTION, UVM_ADVICE マクロはそれぞれ、protection, inheritance, maximum protection, advice を 返します。 uvm_map() は通常の UVM の返値を返します。

uvm_map_pageable() は map マップ上の start から end までのページ範囲のページング可/不可を new_pageable に変えます。 uvm_map_pageable() は UVM 標準の返値を返します。

uvm_map_checkprot() は map マップ上の start から end までの範囲のプロテクションを、 protection についてチェックします。 TRUE または FALSE を返します。

uvm_map_protect() は map マップ上の start から end までのプロテクションを new_prot に変え、また、 set_max が非 0 であればその範囲を new_prot で最大限のプロテクションに設定します。 この関数は UVM 標準の返値を返します。

uvm_deallocate() は map 内の start から start + size のカーネルメモリを割当解除します。

uvmspace_alloc() は min から max の範囲の新しいアドレス空間を割り当てて返します。同時に、そのアドレス空間に pageable のページング許可を設定します。

uvmspace_exec() は、プロセス p のそのアドレス空間が参照されなくなっていた場合は再利用し、もしくは uvmspace_alloc() で新規のものを作成します。

uvmspace_fork() はアドレス空間 vm1 上に新規のアドレス空間を作成し返します。これは主に、 子プロセスのアドレス空間を割り当てるために使用します。

uvmspace_free() はアドレス空間 vm の参照カウンタを減じ、参照が 0 になった場合はデータ構造を解放します。

uvmspace_share() はプロセス p2 が p1 のアドレス空間を共有するようにします。

uvmspace_unshare() はプロセス p が自身の、他と共有しないアドレス空間を持つようにします。必要であれば uvmspace_fork() を呼び出して新しい空間を生成します。

ページ例外のハンドリング

int uvm_fault(vm_map_t orig_map, vaddr_t vaddr, vm_fault_t fault_type, vm_prot_t access_type)

uvm_fault() は例外のメインエントリポイントです。引数として、 例外の発生したマップ orig_map 例外の発生したマップ上のオフセット vaddr 例外のタイプ fault_type 要求されたアクセスの型をあらわす access_type を取ります。 uvm_fault() は UVM 標準の返値を返します。

ファイルとデバイスのメモリへのマッピング

struct uvm_object * uvn_attach(void *arg, vm_prot_t accessprot) void uvm_vnp_setsize(struct vnode *vp, u_quad_t newsize) void uvm_vnp_sync(struct mount *mp) void uvm_vnp_terminate(struct vnode *vp) boolean_t uvm_vnp_uncache(struct vnode *vp)

uvn_attach() V ノード arg へ UVM オブジェクトをアタッチします。必要であればオブジェクトを生成します。 そのオブジェクトを返します。

uvm_vnp_setsize() V ノード vp の大きさを newsize に設定します。 呼び出し側は、この V ノードへの参照を保持したままでなければなりません。 V ノードを縮小した場合、使用されなくなったページは破棄されます。 この関数はファイルシステムと VM バッファのキャッシュが統合されたら 削除します。

uvm_vnp_sync() mp で渡されたマウントポイントの、未同期の V ノードを同期します。 mp が NULL の場合は全ての未同期の V ノードを同期します。 この関数はファイルシステムと VM バッファのキャッシュが統合されたら 削除します。

uvm_vnp_terminate() V ノード vp に割り当てられている VM 資源を全て解放します。 その V ノードへの参照がまだ残っている場合、破棄はされません。ですが、 その後この V ノードに対する操作は全てエラーとなります。 この関数はファイルシステムと VM バッファのキャッシュが統合されたら 削除します。

uvm_vnp_uncache() V ノード vp への全参照がなくなった後には、それが存在しなくなるようにします。 この関数はファイルシステムと VM バッファのキャッシュが統合されたら 削除します。有効な V ノードが無かった場合には、真を返します。

仮想記憶入出力

int uvm_io(vm_map_t map, struct uio *uio)

uvm_io() map で記述されるメモリ上の uio で記述される入出力を実行します。

カーネルメモリの割り当て

vaddr_t uvm_km_alloc(vm_map_t map, vsize_t size) vaddr_t uvm_km_zalloc(vm_map_t map, vsize_t size) vaddr_t uvm_km_alloc1(vm_map_t map, vsize_t size, boolean_t zeroit) vaddr_t uvm_km_kmemalloc(vm_map_t map, struct uvm_object *obj, vsize_t size, int flags) vaddr_t uvm_km_valloc(vm_map_t map, vsize_t size) vaddr_t uvm_km_valloc_wait(vm_map_t map, vsize_t size) struct vm_map * uvm_km_suballoc(vm_map_t map, vaddr_t *min, vaddr_t *max , vsize_t size, boolean_t pageable, boolean_t fixed, vm_map_t submap) void uvm_km_free(vm_map_t map, vaddr_t addr, vsize_t size) void uvm_km_free_wakeup(vm_map_t map, vaddr_t addr, vsize_t size)

uvm_km_alloc() と uvm_km_zalloc() はマップ map に size バイトの固定カーネルメモリを割り当てます。 割り当てに加えて、 uvm_km_zalloc() はメモリをゼロ埋めします。 この両関数は uvm_km_alloc1() を使ったマクロとして定義されており、できるだけ uvm_km_alloc1() よりもこれらを使うべきです。

uvm_km_alloc1() はカーネルマップに size バイトの固定メモリを割り当て、返します。 zeroit 引数が非ゼロの場合は、そのメモリをゼロ埋めします。

uvm_km_kmemalloc() は obj へ size のカーネル固定メモリを割り当て、返します。 フラグは以下のいずれかです:

    #define UVM_KMF_NOWAIT  0x1                     /* M_NOWAIT に一致 */
    #define UVM_KMF_VALLOC  0x2                     /* VA のみ割り当て */
    #define UVM_KMF_TRYLOCK UVM_FLAG_TRYLOCK        /* ロックの試行のみ */

UVM_KMF_NOWAIT では uvm_km_kmemalloc() はメモリがない場合にすぐにリターンします。 UVM_KMF_VALLOC では仮想アドレスを 1 つ割り当てるだけで、ページは割り当てません。 UVM_KMF_TRYLOCK では uvm_km_kmemalloc() はロック時に simple_lock_try() を使用します。

uvm_km_valloc() と uvm_km_valloc_wait() は新規に割り当てた、0 埋めされた size の大きさのカーネルマップのアドレスを返します。 uvm_km_valloc_wait() は、メモリが不足した場合に、カーネルメモリが利用可能になるまで待ちます。

物理メモリの割り当て

struct vm_page * uvm_pagealloc(struct uvm_object *uobj, vaddr_t off, struct vm_anon *anon) void uvm_pagerealloc(struct vm_page *pg, struct uvm_object *newobj, vaddr_t newoff) void uvm_pagefree(struct vm_page *pg) int uvm_pglistalloc(psize_t size, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, struct pglist *rlist, int nsegs, int waitok) void uvm_pglistfree(struct pglist *list) void uvm_page_physload(vaddr_t start, vaddr_t end, vaddr_t avail_start, vaddr_t avail_end)

uvm_pagealloc() はオブジェクト uobj あるいは無記名メモリ anon の仮想アドレス off へメモリページを割り当てます。オブジェクトあるいは無記名メモリは 呼び出し元でロックしておななくてはなりません。 off と uobj のどちらか一方に非 NULL を指定します。 ページが割り当てられない場合は NULL を返します。

uvm_pagerealloc() は新規オブジェクト newobj の新規オフセット newoff へページ pg を再割り当てします。

uvm_pagefree() 物理ページ pg を解放します。

uvm_pglistalloc() は、サイズ size のページリストを、さまざまな条件下で割り当てます。 low と high はそれぞれ、リストに利用可能な最低位と最高位のアドレスを意味します。 alignment が非ゼロの場合、リストの境界値で、2 の乗数をあらわします。 boundary が非ゼロの場合、リストのセグメントは、ゼロからの相対値で、この 2 の乗数の 境界をまたぐことはできません。 引数 nsegs と waitok は現在使用されていません。

uvm_pglistfree() は list で指されるページリストを解放します。

uvm_page_physload() は物理メモリセグメントを VM 空間にロードします。システムのブート時に 物理メモリ管理用のページを用意するために必ず呼び出します。引数は セグメントの物理アドレスの start と end 、および未使用の利用可能アドレスの開始、終了アドレスをあらわします。

uvm_km_suballoc() は map からサブマップを割り当てます。 submap が NULL の場合、新しいマップを作成します。サブマップの具体的なアドレスは 引数 fixed を非ゼロに設定することで指定し、その場合、引数 min はそのサブマップでの開始アドレスの指定となります。 fixed がゼロの場合、大きさ size を map から適当なアドレスで割り当て、開始アドレスと終了アドレスを min と max に返します。 pageable が非ゼロの場合、そのマップのエントリはページアウト可能として扱われます。

uvm_km_free() と uvm_km_free_wakeup() は、カーネルマップの addr を開始アドレスとする大きさ size バイトのメモリを解放します。 uvm_km_free_wakeup() はマップのロック解除の前にそのマップに対して thread_wakeup() を呼び出します。

プロセス

void uvm_pageout() void uvm_scheduler() void uvm_swapin(struct proc *p) void

uvm_pageout() はページデーモンのメインループです。

uvm_scheduler() はプロセス 0 のメインループで、システムが他のプロセスの起動を完了した 後で呼び出されます。走行可能なプロセスをスワップインしたり、優先度に従って スワップアウトしたりします。

uvm_swapin() 指定されたプロセスをスワップインします。

その他の関数

struct uvm_object * uao_create(vsize_t size, int flags) void uao_detach(struct uvm_object *uobj) void uao_reference(struct uvm_object *uobj) boolean_t uvm_chgkprot(caddr_t addr, size_t len, int rw) void uvm_kernacc(caddr_t addr, size_t len, int rw) boolean_t uvm_useracc(caddr_t addr, size_t len, int rw) void uvm_vslock(struct proc *p, caddr_t addr, size_t len) void uvm_vsunlock(struct proc *p, caddr_t addr, size_t len) void uvm_meter() int uvm_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp , size_t newlen, struct proc *p) void uvm_fork(struct proc *p1, struct proc *p2, boolean_t shared) int uvm_grow(struct proc *p, vaddr_t sp) int uvm_coredump(struct proc *p, struct vnode *vp, struct ucred *cred, struct core *chdr)

uao_create(), uao_detach(), uao_reference() は、System V 共有メモリのサポート等に使用する、無記名メモリオブジェクトを 操作します。 uao_create() は大きさ size で次のフラグ値のオブジェクトを返します:

    #define UAO_FLAG_KERNOBJ        0x1     /* カーネルオブジェクトを作成 */
    #define UAO_FLAG_KERNSWAP       0x2     /* カーネルスワップ可能 */

システムのブート時に一度だけ使用します。 uao_reference() は指定の無記名メモリオブジェクトへの参照を追加作成します。 uao_detach() は指定の無記名メモリオブジェクトへの参照を削除し、参照が無くなった場合は そのオブジェクトを消去します。

uvm_chgkprot() はカーネルメモリの addr から addr + len までの保護状態を rw に変更します。 この関数は主に、デバッガがブレークポイントを設定するために使います。 この関数はコンフィグレーション時に KGDB オプションを指定した場合のみ有効になります。

uvm_kernacc() と uvm_useracc() は、それぞれ、カーネルアドレス空間とカレントプロセスのアドレス空間の addr から addr + len までに対する rw アクセスの確認を行います。

uvm_vslock() と uvm_vsunlock() は、プロセス p が addr から addr + len までのページへの書き出しの可否制御します。 これらの関数は通常、メモリを I/O 用に固定するために使用します。

uvm_meter() 負荷平均を計算し、必要であればスワッパを起こします。

uvm_sysctl() は sysctl(3) 階層の CTL_VM ドメインを扱えるようにします。 uvm_sysctl() は VM_LOADAVG, VM_METER, VM_UVMEXP の呼び出しを扱い、それぞれ、現在の負荷平均を返し、VM の総量計算を行い、 uvmexp 構造体を返します。負荷平均はユーザ領域から getloadavg(3) 関数で取得できます。uvmexp 構造体は UVM システムの全ての大域状態を 保持しており、以下のメンバがあります:

    /* vm_page 定数 */
    int pagesize;   /* 1 ページの大きさ (PAGE_SIZE): 2 の乗数 */
    int pagemask;   /* ページマスク */
    int pageshift;  /* ページシフト */
    /* vm_page カウンタ */
    int npages;     /* 管理しているページの数 */
    int free;       /* 空きページの数 */
    int active;     /* アクティブなページの数 */
    int inactive;   /* 解放したが、後で使いそうなページの数 */
    int paging;     /* ページアウトされたプロセスのページ数 */
    int wired;      /* 固定ページの数 */
    int reserve_pagedaemon; /* ページデーモン用に予約されたページ数 */
    int reserve_kernel; /* カーネル用に予約されたページ数 */
    /* ページアウトパラメータ */
    int freemin;    /* 空きページの最小値 */
    int freetarg;   /* 空きページの目標数 */
    int inactarg;   /* 非アクティブなページの目標数 */
    int wiredmax;   /* 固定ページの最大数 */
    /* スワップ */
    int nswapdev;   /* システムで設定されているスワップデバイスの数 */
    int swpages;    /* PAGE_SIZE でのスワップページの数 */
    int swpginuse;  /* 使用中のスワップページ数 */
    int nswget;     /* uvm_swap_get() を呼び出した例外の回数 */
    int nanon;      /* システム内の無記名メモリの数 */
    int nfreeanon;  /* 空き無記名メモリの数 */
    /* 状態カウンタ */
    int faults;             /* ページ例外カウント */
    int traps;              /* トラップカウント */
    int intrs;              /* 割込カウント */
    int swtch;              /* コンテクストスイッチカウント */
    int softs;              /* ソフトウエア割込カウント */
    int syscalls;           /* システムコール数 */
    int pageins;            /* ページイン操作カウント */
                            /* ページアウトは下の pdpageouts */
    int swapins;            /* スワップイン回数 */
    int swapouts;           /* スワップアウト回数 */
    int pgswapin;           /* スワップインしたページ数 */
    int pgswapout;          /* スワップアウトしたページ数 */
    int forks;              /* fork 数 */
    int forks_ppwait;       /* 親が wait する fork の数 */
    int forks_sharevm;      /* VM 空間を共有する fork の数 */
    /* 例外サブカウンタ */
    int fltnoram;   /* RAM 不足となった例外の回数 */
    int fltnoanon;  /* 無記名のものの不足となった例外の回数 */
    int fltpgwait;  /* あるページで待ち状態となった例外の回数 */
    int fltpgrele;  /* 解放済みページがあった例外の回数 */
    int fltrelck;   /* 再ロックが呼び出された例外の回数 */
    int fltrelckok; /* 再ロックが成功した例外の回数 */
    int fltanget;   /* 無記名ページを取得した例外の回数 */
    int fltanretry; /* 無記名ページを取得のリトライを行った例外の回数 */
    int fltamcopy;  /* "要複製" をクリアした例外の回数 */
    int fltnamap;   /* 隣りの無記名ページをマップした例外の回数 */
    int fltnomap;   /* 隣りのオブジェクトページをマップした例外の回数 */
    int fltlget;    /* ロックされた pgo_get を行った例外の回数 */
    int fltget;     /* 非ロックの get を行った例外の回数 */
    int flt_anon;   /* 無記名のものの例外の回数 (ケース 1a) */
    int flt_acow;   /* 無記名の cow の例外の回数 (ケース 1b) */
    int flt_obj;    /* オブジェクトページでの例外の回数 (2a) */
    int flt_prcopy; /* コピーを起こした例外の回数 (2b) */
    int flt_przero; /* ゼロ埋めを起こした例外の回数 (2b) */
    /* デーモンカウンタ */
    int pdwoke;     /* デーモンが起きた回数 */
    int pdrevs;     /* デーモンが rev'd clock hand した回数(?) */
    int pdswout;    /* デーモンがスワップアウトで呼び出された回数 */
    int pdfreed;    /* デーモンがブート以来解放したページ数 */
    int pdscans;    /* デーモンがブート以来解走査したページ数 */
    int pdanscan;   /* デーモンが走査した無記名ページの数 */
    int pdobscan;   /* デーモンが走査したオブジェクトページの数 */
    int pdreact;    /* デーモンがブート以来再度アクティブにしたページの数 */
    int pdbusy;     /* デーモンが使用中ページと認識した回数 */
    int pdpageouts; /* デーモンがページアウトを開始した回数 */
    int pdpending;  /* デーモンがページアウト待ちを受け取った回数 */
    int pddeact;    /* デーモンが非アクティブ状態とした回数 */

uvm_fork() はプロセス p1 (元) と p2 (新) の仮想アドレス空間の fork を行います。 shared 引数が非ゼロの場合、 p1 は p2 とアドレス空間を共有し、そうでなければ新しいアドレス空間を生成します。 この関数は現状返値を持ちません。したがって、エラーになることはありません。 将来は、メモリ不足の場合にはエラーにできるように変更する予定です。

uvm_grow() はプロセス p のスタックセグメントを sp を含むように拡げます。

uvm_coredump() は V ノード vp 上に、クリデンシャル cred 、 chdr のコアヘッダ情報でプロセス p のコアダンプを生成します。

UVM 標準返値
この章は UVM 関数を呼び出した場合に想定しておくことのできる標準の返値に ついて記しています。これらは Mach VM の同じ関数のものを引き継いでいます。 値の全リストは以下です。

    #define KERN_SUCCESS            0
    #define KERN_INVALID_ADDRESS    1
    #define KERN_PROTECTION_FAILURE 2
    #define KERN_NO_SPACE           3
    #define KERN_INVALID_ARGUMENT   4
    #define KERN_FAILURE            5
    #define KERN_RESOURCE_SHORTAGE  6
    #define KERN_NOT_RECEIVER       7
    #define KERN_NO_ACCESS          8
    #define KERN_PAGES_LOCKED       9

KERN_NOT_RECEIVER と KERN_PAGES_LOCKED は UVM のコードでは実際には返さないので注意して下さい。

注意
これらの関数は UVM オプションを指定した場合のみ有効になります。

uvm_chgkprot() は KGDB オプションを指定してカーネルをコンパイルした場合のみ有効です。

インクルードファイル <vm/vm.h> は、Mach VM システムを使用しなくなった時点で無くなります。``vm_'' の 接頭の構造体や型は ``uvm_'' に変更する予定です。

pmap(9) のマニュアルページはまだ書かれていません。

歴史
UVM は、セントルイス (ミズーリ州) のワシントン大学で開発された新しい VM システムです。UVM は、Mach ベースの 4.4BSD VM システム、FreeBSD の VM システム、SunOS4 の VM システムを元にした 部分も含んでいます。UVM の基本的な構造は 4.4BSD VM システムのものをベースにしています。 UVM の i386 アーキテクチャ依存レイヤは FreeBSD のアイデアを含んでいます。 UVM の新しい無記名メモリシステムは、SunOS4 の VM の無記名メモリシステム (Sun Microsystems 社のペーパーに述べられています) を参考にしています。 UVM はさらに、ページレイアウト、マップエントリの受渡し、簡潔になった copy-on-write、無記名メモリページアウトのクラスタ化など、 たくさんの BSD に無かった特徴を持っています。UVM は 1998 年 8 月の Charles D. Cranor の論文でさらに詳しく述べられる予定です。

UVM は NetBSD 1.4 で初めて登場しました。

作者
Charles D. Cranor <chuck@ccrc.wustl.edu> が UVM の設計と実装を行いました。

Matthew Green <mrg@eterna.com.au> はスワップ空間を管理するコードの記述と、 UVM の NetBSD のソースツリーへの統合などに骨をおりました。

Chuck Silvers <chuq@chuq.com> は aobj ページャを実装しました。このおかげで、 UVM は System V の共有メモリとプロセススワッピングをサポートできました。

関連項目
getloadavg(3), kvm(3), sysctl(3), ddb(4), options(4)