Upload
magoroku-yamamoto
View
1.267
Download
1
Embed Size (px)
Citation preview
自分でOSを作っている人のための、仮想記憶構築法
At Geekbar
2011/6/13
@magoroku15
今日のお話
対象 自分でOSを作っている人 AND
仮想記憶のついて理解はしている AND
OSの教科書を読んでみたけどよくわからない AND
具体的な実装を見てみたい 人
内容 仮想記憶の構成について
空間構成 単一空間、多重空間
4.3BSDを例にした実装の紹介
空間の構成
単一空間構成
1枚の空間を仮想化する
1枚の空間に複数のプロセスが同居
メモリの拡張が主な目的利用
多重空間構成
複数の空間を仮想化する
1枚の空間に1個のプロセスが存在
システムの保護が主な利用目的
空間の構成
多重空間
単一空間
多重仮想空間の作り方
アプリ
OS
物理メモリ管理構造
仮想-物理 空間変換表
アドレス変換 1of3
アドレスの変換単位はページ 大きさ数Kbyte
aligned
仮想アドレスのページ番号を実アドレスのページ番号に置換
アドレスの変換表をOSが用意して、CPU(MMU)に通知
アドレス変換表
アドレス変換 2of3
アドレス32bit、ページサイズ4Kbyte場合
4Kbyteは0x1000 16進で3桁は変換表に含まない
ページ番号 ページ内オフセット
アドレス変換 3of3
アドレス変換表
仮ページ番号
仮想アドレス
ページ内オフセット
ページ番号
実ページ番号
実ページ番号
実アドレス
ページ内オフセット
変換機構の実例
変換表を2段に
ページ 4Kbyte
セグメント 1Mbyte
変換キャッシュ
ページ番号セグメント番号 ページ内オフセット
セグメントテーブルページテーブル
仮ページ番号
仮ページ番号
実ページ番号仮ページ番号
変換キャッシュ
ページング
一般的な運用では
仮想空間量の総量 > 物理メモリ
物理メモリの奪い合い
メモリ参照に局所性がある状況では
ゆっくり奪い合う→そこそこ動く
メモリ参照に局所性がない状況では
はげしく奪い合う→動かない
局所的な参照の検出が重要
どうやって
Least Recently Used (LRU)
最近使われていないメモリは、今後も使われない -たぶんね ;-)
メモリの参照頻度を記録して、今後使われないメモリを予想する
仮想記憶をサポートする最近のCPUは、参照の有無を変換表に(1bit)記録する
OSが、この情報を定期的にクリアしながら記録する
ソースを読む
4.3BSD
1986年にカリフォルニア大学バークレー校によって配布された近代UNIX
http://www.tamacom.com/tour/kernel/bsd/
sys/vm_page.c
ページング処理が記述
構造:cmap
h/cmap.h27 struct cmap
28 {
29 unsigned short c_next, /* index of next free list entry */
30 c_prev, /* index of previous free list entry */
31 c_hlink; /* hash link for <blkno,mdev> */
32 unsigned short c_ndx; /* index of owner proc or text */
33 unsigned int c_page:21, /* virtual page number in segment */
34 c_lock:1, /* locked for raw i/o or pagein */
35 c_want:1, /* wanted */
36 c_intrans:1, /* intransit bit */
37 c_free:1, /* on the free list */
38 c_gone:1, /* associated page has been released */
39 c_type:2, /* type CSYS or CTEXT or CSTACK or CDATA */
40 :4, /* to longword boundary */
41 c_blkno:24, /* disk block this is a copy of */
42 c_mdev:8; /* which mounted dev this is from */
43 };
構造:pte
vax/pte.h
20 struct pte
21 {
22 unsigned int pg_pfnum:21, /* core page frame number or 0 */
23 :2,
24 pg_vreadm:1, /* modified since vread (or with _m) */
25 pg_swapm:1, /* have to write back to swap */
26 pg_fod:1, /* is fill on demand (=0) */
27 pg_m:1, /* hardware maintained modified bit */
28 pg_prot:4, /* access control */
29 pg_v:1; /* valid bit */
30 };
pageout()
sys/vm_page.c696 loop:
711 sleep((caddr_t)&proc[2], PSWP+1);
712 (void) spl0();
713 count = 0;
714 pushes = 0;
715 while (nscan < desscan && freemem < lotsfree) {
720 if (checkpage(fronthand, FRONT))
721 count = 0;
722 if (checkpage(backhand, BACK))
723 count = 0;
724 cnt.v_scan++;
725 nscan++;
:
:
741 }
742 goto loop;
743 }
744
checkpage
sys/vm_page.c768 top:
774 c = &cmap[hand];
775 if (c->c_lock || c->c_free)
776 return (0);
777 switch (c->c_type) {
779 case CSYS:
780 return (0);
789 case CDATA:
790 case CSTACK:
791 rp = &proc[c->c_ndx];
792 while (rp->p_flag & SNOVM)
793 rp = rp->p_xlink;
794 xp = rp->p_textp;
795 if (c->c_type == CDATA) {
796 v = dptov(rp, c->c_page);
797 pte = dptopte(rp, c->c_page);
:
802 break;
803 }
:
813 if (pte->pg_v) {
814 if (whichhand == BACK)
815 return(0);
816 pte->pg_v = 0;
817 if (anycl(pte, pg_m))
818 pte->pg_m = 1;
819 distcl(pte);
:
825 }
こんなかんじ
cmap 物理メモリ管理構造
仮想-物理 空間変換表
FRONT
BACK
一定の距離
FRONTハンドがスキャンした後にBACKがスキャン。参照されていなければ参照されていない
proc プロセス管理構造
c_ndx;
c_page:
c_pageとc_ndxを使ってpteを求めて、無効化してswapに書き出す
まとめ
pageout処理に絞って処理を俯瞰
他のOSもほぼ同じ
実メモリ(page)の管理構造
利用状況を検出
実メモリから、アドレス変換エントリを算出
変換を無効化してswapに追い出す
どこに追い出したかを記録
これで、仮想記憶の拡張も書けますね
そういえば
UNIX V7に仮想記憶を書き足した学生がいましたね
minixっていうUNIXもどきの学習用のOSに仮想記憶を書き足した学生もいましたね