KEMBAR78
Basic of virtual memory of Linux | PDF
組込みエンジニアのためのLinux入門
     仮想メモリ編
    2007.2.22 original
    2012.10.27 revival

        小林哲之
                         1
注釈
• このスライドは2007年に作成して、CELFテク
  ニカルジャンボリーで発表したものです。
•   http://tree.celinuxforum.org/CelfPubWiki/JapanTechnicalJamboree13

• 内容的には現在でもほぼ通用するので再演
  します。




                                                         2
このスライドの対象とする方
• 今までずっと組込み機器のプロジェクト
  に携わってきて最近はOSにLinuxを使っ
  ている方々
このスライドの目的
• Linuxの仮想メモリの仕組みを理解し現
  在のプロジェクトに役立てる。
 – 仕組みを知らなくてもプログラムは動くが、
   性能を引き出すためには仕組みの理解が
   重要。




                 4
まず基本の概念から
• 仮想~、論理~ virtual, logical
  – 仮想アドレス、論理デバイス、論理セ
    クタ、仮想マシン
  – あたかも ... のように扱う
• 実~、物理~ real, physical
  – 実アドレス、物理デバイス、物理セクタ
  – そのもの、そのまんま
                   5
仮想化: あたかも・・・ 実は
•   あたかも巨大のようだが、実は少ない。
•   あたかも平らのようだが、実は凸凹。
•   あたかもたくさんのようだが、実はひとつ。
•   あたかも占有しているようだが、実は共有。
    仮想化は複雑さや個々に依存することを
    隠蔽するマジック。
    マジックなので種も仕掛けもある。
     = 実と仮想の対応付け(マッピング)
     あたかもそう見えるように変換している。
                    6
仮想化の代償
• マイナス面よりもプラス面が勝っている
  から仮想化を行うわけだが、常にプラス
  とは限らない。




               7
物理メモリと仮想メモリ
• いままでの大抵の組込み機器プロジェクトで
  は物理メモリしか扱うことがなかった。
• 最近は組み込みシステムの規模の増大化に
  伴ってLinuxやWindow CEなどPC向けOSの
  流れを持つOSを使用することが多くなってき
  た。これらのOSは仮想メモリシステムを備え
  ている。
• このスライドではLinuxについて説明する。

                      8
物理メモリ
• 単一のメモリ空間
• 機器ごとにROM,RAM,I/Oの
                          ROM
  実装アドレスが異なるので
  それを意識してプログラムする
                          RAM



                          I/O

                          I/O

                          I/O
                      9
仮想メモリ
• 利点
 – ユーザープログラムは実際のメモリマップ(実装アドレス、
   実装サイズ)に依存しなくなる。
 – 不連続な物理メモリの断片を連続する仮想メモリとして利
   用できる。
 – メモリ保護:バグによって無関係の部分のメモリが破壊さ
   れることを防止できる。
• 新しい概念の導入
 – アドレス変換
 – 多重メモリ空間
 – デマンドページング

                      10
仮想メモリの概念図




出典: フリー百科事典『ウィキペディア(Wikipedia)』
                                  11
アドレス変換
仮想アドレス空間                   物理アドレス空間

                             ROM



                            アドレスy
                             RAM
               MMU

                              I/O
 アドレスx
            Linux kernel
                              I/O
            がコントロー
                 ル            I/O

                             12
仮想メモリはCPUの中だけ
 仮想アドレス空間
                     物理アドレス空間

                       ROM



                      アドレスy
                       RAM
               MMU

 アドレスx                  I/O

                        I/O
         CPU            I/O

CPUから外にでてくるアドレスバスにのるのは物理アドレスだけ。
ロジアナでは仮想アドレスは観測できない。    13
ユーザープログラムは仮想アドレスだけ
  仮想アドレス空間        物理アドレス空間
                    ROM


                   アドレスy
                    RAM
            MMU
  アドレスx             I/O
                    I/O
          CPU       I/O


 物理アドレスを扱うのはカーネルモードだけ。
 つまりカーネル本体とデバイスドライバ。
                          14
MMUでのアドレス変換
                 31          22 21             12 11                 0
仮想アドレス           Directory Index   Page Table Index    Page Offset


Page Directory
Base Register
                        Page Directory

                         Directory             Page Table
                          Entry                                 No page! ... page fault

                                               Page Table        Page
                                                 Entry
                                                                 物理アドレス



                                                                     15
TLB
       仮想アドレスページ         物理アドレスページ




                   ...


• Translation Lookaside Buffers
• 仮想アドレスをkeyとして物理アドレスを得る
  ハッシュテーブルのようなもの
• 大抵のアドレス変換はTLBにヒットするので
  実際にPage Directory, Page Tableをアクセ
  スせずに済む。
                                     16
多重メモリ空間
プロセスごとに独立した仮想メモリ空間
                     物理アドレス空間

                       ROM




                       RAM

                        I/O

                        I/O

                       17
デマンドページング
•    ページ単位でマッピングされる
     – ページのサイズはたいていは4Kbytes
•    2段階で行われる
     1. 仮想メモリの割り当て(mmap)
        管理台帳に登録するだけ
     2. 実際にアクセスがあったときに初めて
        そのページに物理メモリが割り当てられる

    アクセスのないページには物理メモリが割り当てられないので
    仮想メモリサイズ >= 実際に必要な物理メモリサイズ
                           18
デマンドページングの動作例
(1)
              仮想アドレス空間   物理アドレス空間


read access

                      対応する
                     物理ページが
                      ない!




          ページフォールト発生
          カーネルモードへ
                                    19
デマンドページングの動作例(続)
(2)
      仮想アドレス空間   物理アドレス空間




                       DMA転送
           マッピング

カーネルがデータをロードして物理アドレスをマッピングする。
                            20
デマンドページングの動作例(続)
(3)
             仮想アドレス空間   物理アドレス空間



      data




      ユーザーモードに復帰。
      ユーザープログラムからは何事もなかったように
      データが読める。 ... でも実際に時間はかかっている。
                                   21
ページキャッシュ

       物理アドレス空間




ディスクからの読んだ内容はメモリに余裕がある限り保持しておく。
シーケンシャルにアクセスされる場合が多いので数ページ分を
まとめて先読みを行う。
そのため(2)では毎回ディスクアクセスが発生するとは限らない。
                       22
ページアウト

(2)で物理メモリの空きがなかった場合、使用頻度の低いと思われるページを
解放する。そのページの内容が変更されていなければそのまま破棄。
変更されていればスワップデバイスに掃きだす。
       仮想アドレス空間   物理アドレス空間




                                 swap device


掃きだす              ただし組込みLinuxではswap deviceを装備していない
ページ               ことが多い。           23
ページアウト(続)

解放した分のページを使って要求されたページの割り当てを行う。
このような「お手玉」をすることで実際に搭載されている物理メモリサイズ
よりも大きなサイズの仮想メモリを扱うことができる。
     仮想アドレス空間    物理アドレス空間




                          DMA転送
                no page

                                  24
ページの共有
 仮想アドレス空間
プロセスA

              物理アドレス空間




            同じファイルの同じページは複数の
            プロセスから共有される。
   プロセスB
            Read onlyのページだけでなく
                            25
            write可のページも。
コピーオンライト

         プロセスA
                   Write可でプライベートのページに
                   書き込みが発生すると・・・
write
access           r/w private




                                 ページフォルト
                                   発生



                               read only


            プロセスB
                                      26
コピーオンライト(続)

         プロセスA
write
access



                            read/write

                                    copy
                            read only


                    カーネルはコピーしてページの設定を
            プロセスB
                    read/writeに変更する
                               27
プロセスのメモリ空間
                       process A     B      C
     0x00000000




                       user space                ...

         1プロセスあたり約3GBのユーザメモリ空間


     TASK_SIZE
                        kernel
                                    カーネルの空間は各プロセスで共通。
                        space       カーネルの空間はユーザーモードでは
          0xffffffff                Read/Write/Execute不可。
TASK_SIZEはi386では0xc0000000          プロセス切り替えに伴ってユーザーメモリ
ARMでは 0xbf000000                    空間が切り替わる。           28
ユーザプロセスのメモリ空間の実例
cat /proc/<PROCESS_ID>/maps
00101000-0011a000   r-xp   00000000   fd:00   15172739   /lib/ld-2.4.so
0011a000-0011b000   r-xp   00018000   fd:00   15172739   /lib/ld-2.4.so
0011b000-0011c000   rwxp   00019000   fd:00   15172739   /lib/ld-2.4.so
0011e000-0024a000   r-xp   00000000   fd:00   15172740   /lib/libc-2.4.so
0024a000-0024d000   r-xp   0012b000   fd:00   15172740   /lib/libc-2.4.so
0024d000-0024e000   rwxp   0012e000   fd:00   15172740   /lib/libc-2.4.so
0024e000-00251000   rwxp   0024e000   00:00   0
08048000-08049000   r-xp   00000000   fd:00   11666681   /home/koba/lab/loop/a.out
08049000-0804a000   rw-p   00000000   fd:00   11666681   /home/koba/lab/loop/a.out
b7fef000-b7ff1000   rw-p   b7fef000   00:00   0
b7fff000-b8000000   rw-p   b7fff000   00:00   0
bffeb000-c0000000   rw-p   bffeb000   00:00   0          [stack]

 アドレス範囲                     file offset        inode      file name
                           r: read      device
                           w: write major:minor
                           x: execute
                           s: shared
                                                                   29
                           p: private (copy on write)
ユーザプロセスのメモリ空間の実例
         (詳細)
cat /proc/<PROCESS_ID>/smaps
      ....
0011e000-0024a000 r-xp 00000000 fd:00 15172740   /lib/libc-2.4.so
Size:              1200 kB
Rss:                136 kB     RSS = 物理メモリサイズ
Shared_Clean:       136 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:        0 kB
0024a000-0024d000 r-xp 0012b000 fd:00 15172740   /lib/libc-2.4.so
Size:                12 kB
Rss:                  8 kB
Shared_Clean:         0 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:        8 kB
0024d000-0024e000 rwxp 0012e000 fd:00 15172740   /lib/libc-2.4.so
Size:                 4 kB
Rss:                  4 kB
Shared_Clean:         0 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:        4 kB                               30
      ....
システムコールmmap
#include <sys/mman.h>

void *mmap(void *start, size_t length, int prot, int flags,
        int fd, off_t offset);

int munmap(void *start, sizt_t length);


• ファイルやデバイスをメモリにマップ/アンマップする
• 引数 prot
   – PROT_NONE または PROT_EXEC, PROT_READ,
     PROT_WRITEのOR演算
• 引数 flags
   – MAP_FIXED, MAP_SHARED, MAP_PRIVATE,
     MAP_ANONYMOUS, ...
                                                 31
mmapのtips
• MAP_FIXEDを指定しなければカーネルが空
  いているページをさがしてくれる。
• MAP_FIXEDを指定したときに既存のページ
  と重なっていたら、そのページは内部的に
  munmapされる。
 – なのでこのオプションは通常は使用しない。
• ファイルのオフセットはページサイズの整数
  倍でなければならない。
• mmapとmunmapのアドレス、サイズは一致
  していなくてもよい。
                    32
mmapの使い方(1)
• 巨大サイズのmallocの代用
 – コンパクションなどデータのコピーが発生しない。
 – malloc/freeと違ってmunmapするときのaddr, size
   はmmapで確保したときと異なっていてもよい。
    • まとめて1回のmmapで確保して少しづつ分割し
      てmunmapで返却するのもあり。
 – glibcのmallocの実装ではある一定以上のサイズ
   のmallocはmmapを呼び出す。
   • DEFAULT_MMAP_THRESHOLD = (128*1024)


                                           33
mmapの使い方(2)
• 高速なファイルアクセス
 – read, writeのシステムコールでは内部で物
   理ページにバッファリングしている。そこか
   らユーザの指定した配列にコピーしている
   。
 – mmapを使うことで直接ページにアクセス
   できるようになるのでデータのコピーを減ら
   すことができる。
 – Java1.4の java.nio.MappedByteBuffer
                             34
mmapの使い方(3)
• プロセス間の共有メモリ
 – 複数のプロセスから同じファイルをR/W可
   sharedでマッピングする。
 – IPCの共有メモリのシステムコール
   (shmget, shmat,..)は内部で同様のことを
   行っている。



                        35
mmapの使い方(4)
• 物理メモリ、I/Oポートのアクセス
 – デバイスファイル /dev/mem をマッピング
   することでユーザーモードで物理メモリ空
   間をread/writeすることが可能。
 – /dev/memをアクセスするにはrootの権限
   が必要。



                     36
まとめ
• 仮想メモリの使用量と物理メモリの使用
  量は異なる。実際に問題になるのは物
  理メモリの使用量。
• 仮想メモリのオーバーヘッドはいつ発生
  するのかを意識する。
 – TLBミス
 – ページフォルト
• システムコールmmapの活用。
                   37
参考文献
• Linux kernel ソース
  http://www.kernel.org/
• GNU C ライブラリのソース
 http://www.gnu.org/software/libc/
• “詳解LINUXカーネル 第2版”
  オライリージャパン
• “Linuxカーネル2.6解読室”
   SoftBank Creative
• Linux manコマンド
• その他たくさんのWEB検索結果
                                     38
2007年当時

        おまけ:最近の話題
• CELFのBootTimeResourcesより
  – KernelXIP
                           NORフラッシュが
  – ApplicationXIP         使われなくなったため
                           あまり聞かなくなった。
  – (DataReadInPlace)
• CELFのMemoryManagementResoucesより
  – Huge/large/superpages
  – Page cache compression → zramの名前でメインライン
                             化。
                             3.8ではstaging卒業の見込
                             み。
                                 39

Basic of virtual memory of Linux