自分で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.h
27 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.c
696 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.c
768 top:                                            802       break;
774        c = &cmap[hand];                         803   }
775        if (c->c_lock || c->c_free)               :
776              return (0);                        813   if (pte->pg_v) {
777        switch (c->c_type) {                     814         if (whichhand == BACK)
779        case CSYS:                               815               return(0);
780              return (0);                        816         pte->pg_v = 0;
                                                    817         if (anycl(pte, pg_m))
789        case CDATA:                              818               pte->pg_m = 1;
790        case CSTACK:                             819         distcl(pte);
791             rp = &proc[c->c_ndx];                :
792             while (rp->p_flag & SNOVM)          825   }
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);
 :
こんなかんじ
  FRONTハンドがスキャンし
  た後にBACKがスキャン。参
  照されていなければ参照さ
  れていない


             c_pageとc_ndxを
             使ってpteを求め
FRONT        て、無効化して
             swapに書き出す
一定の距離

                                              仮想-物理 空間変換表
BACK
                             c_page:



                              c_ndx;



        cmap 物理メモリ管理構造                 proc プロセス管理構造
まとめ
   pageout処理に絞って処理を俯瞰
   他のOSもほぼ同じ
     実メモリ(page)の管理構造
     利用状況を検出

     実メモリから、アドレス変換エントリを算出

     変換を無効化してswapに追い出す

     どこに追い出したかを記録
   これで、仮想記憶の拡張も書けますね
   そういえば
     UNIX V7に仮想記憶を書き足した学生がいま
      したね
     minixっていうUNIXもどきの学習用のOSに仮
      想記憶を書き足した学生もいましたね

仮想記憶の構築法

  • 1.
  • 2.
    今日のお話  対象  自分でOSを作っている人 AND  仮想記憶のついて理解はしている AND  OSの教科書を読んでみたけどよくわからない AND  具体的な実装を見てみたい 人  内容  仮想記憶の構成について  空間構成 単一空間、多重空間  4.3BSDを例にした実装の紹介
  • 3.
    空間の構成  単一空間構成  1枚の空間を仮想化する  1枚の空間に複数のプロセスが同居  メモリの拡張が主な目的利用  多重空間構成  複数の空間を仮想化する  1枚の空間に1個のプロセスが存在  システムの保護が主な利用目的
  • 4.
  • 5.
    多重仮想空間の作り方 アプリ 仮想-物理 空間変換表 OS 物理メモリ管理構造
  • 6.
    アドレス変換 1of3 アドレス変換表  アドレスの変換単位 はページ  大きさ数Kbyte  aligned  仮想アドレスのページ 番号を実アドレスのペ ージ番号に置換  アドレスの変換表を OSが用意して、CPU( MMU)に通知
  • 7.
    アドレス変換 2of3  アドレス32bit、ページサイズ4Kbyte場合  4Kbyteは0x1000  16進で3桁は変換表に含まない ページ番号 ページ内オフセット
  • 8.
    アドレス変換 3of3 仮想アドレス アドレス変換表 実アドレス 仮ページ番号 ページ内 実ページ番号 ページ内 オフセット オフセット ページ 番号 実ページ番号
  • 9.
    変換機構の実例  変換表を2段に  ページ 4Kbyte セグメント番号 ページ番号 ページ内 オフセット  セグメント 1Mbyte 仮ページ番号  変換キャッシュ セグメントテーブル ページテーブル 仮ページ番号 変換キャッシュ 仮ページ番号 実ページ番号
  • 10.
    ページング  一般的な運用では  仮想空間量の総量 > 物理メモリ  物理メモリの奪い合い  メモリ参照に局所性がある状況では  ゆっくり奪い合う→そこそこ動く  メモリ参照に局所性がない状況では  はげしく奪い合う→動かない  局所的な参照の検出が重要  どうやって
  • 11.
    Least Recently Used(LRU)  最近使われていないメモリは、今後も使わ れない -たぶんね ;-)  メモリの参照頻度を記録して、今後使われ ないメモリを予想する  仮想記憶をサポートする最近のCPUは、 参照の有無を変換表に(1bit)記録する  OSが、この情報を定期的にクリアしながら記 録する
  • 12.
    ソースを読む  4.3BSD  1986年にカリフォルニア大学バークレー校に よって配布された近代UNIX  http://www.tamacom.com/tour/kernel/bsd/  sys/vm_page.c  ページング処理が記述
  • 13.
    構造:cmap  h/cmap.h 27 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 };
  • 14.
    構造: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 };
  • 15.
    pageout()  sys/vm_page.c 696 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
  • 16.
    checkpage  sys/vm_page.c 768 top: 802 break; 774 c = &cmap[hand]; 803 } 775 if (c->c_lock || c->c_free) : 776 return (0); 813 if (pte->pg_v) { 777 switch (c->c_type) { 814 if (whichhand == BACK) 779 case CSYS: 815 return(0); 780 return (0); 816 pte->pg_v = 0; 817 if (anycl(pte, pg_m)) 789 case CDATA: 818 pte->pg_m = 1; 790 case CSTACK: 819 distcl(pte); 791 rp = &proc[c->c_ndx]; : 792 while (rp->p_flag & SNOVM) 825 } 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); :
  • 17.
    こんなかんじ FRONTハンドがスキャンし た後にBACKがスキャン。参 照されていなければ参照さ れていない c_pageとc_ndxを 使ってpteを求め FRONT て、無効化して swapに書き出す 一定の距離 仮想-物理 空間変換表 BACK c_page: c_ndx; cmap 物理メモリ管理構造 proc プロセス管理構造
  • 18.
    まとめ  pageout処理に絞って処理を俯瞰  他のOSもほぼ同じ  実メモリ(page)の管理構造  利用状況を検出  実メモリから、アドレス変換エントリを算出  変換を無効化してswapに追い出す  どこに追い出したかを記録
  • 19.
    これで、仮想記憶の拡張も書けますね  そういえば  UNIX V7に仮想記憶を書き足した学生がいま したね  minixっていうUNIXもどきの学習用のOSに仮 想記憶を書き足した学生もいましたね