組 込 みエンジニアのためのLinux 入 門 仮 想 メモリ 編 2007.2.22 株 式 会 社 アプリックス 小 林 哲 之 1
このスライドの 対 象 とする 方 今 までずっと 組 込 み 機 器 のプロジェクト に 携 わってきて 最 近 はOSにLinuxを 使 っ ている 方 々 2
このスライドの 目 的 Linuxの 仮 想 メモリの 仕 組 みを 理 解 し 現 在 のプロジェクトに 役 立 てる 仕 組 みを 知 らなくてもプログラムは 動 くが 性 能 を 引 き 出 すためには 仕 組 みの 理 解 が 重 要 3
まず 基 本 の 概 念 から 仮 想 ~ 論 理 ~ virtual, logical 仮 想 アドレス 論 理 デバイス 論 理 セ クタ 仮 想 マシン あたかも... のように 扱 う 実 ~ 物 理 ~ real, physical 実 アドレス 物 理 デバイス 物 理 セクタ そのもの そのまんま 4
仮 想 化 : あたかも 実 は あたかも 巨 大 のようだが 実 は 少 ない あたかも 平 らのようだが 実 は 凸 凹 あたかもたくさんのようだが 実 はひとつ あたかも 占 有 しているようだが 実 は 共 有 仮 想 化 は 複 雑 さや 個 々に 依 存 することを 隠 蔽 するマジック マジックなので 種 も 仕 掛 けもある = 実 と 仮 想 の 対 応 付 け(マッピング) あたかもそう 見 えるように 変 換 している 5
仮 想 化 の 代 償 マイナス 面 よりもプラス 面 が 勝 っている から 仮 想 化 を 行 うわけだが 常 にプラス とは 限 らない 6
物 理 メモリと 仮 想 メモリ いままでの 大 抵 の 組 込 み 機 器 プロジェクトで は 物 理 メモリしか 扱 うことがなかった 最 近 は 組 み 込 みシステムの 規 模 の 増 大 化 に 伴 ってLinuxやWindow CEなどPC 向 けOSの 流 れを 持 つOSを 使 用 することが 多 くなってき た これらのOSは 仮 想 メモリシステムを 備 え ている このスライドではLinuxについて 説 明 する 7
物 理 メモリ 単 一 のメモリ 空 間 機 器 ごとにROM,RAM,I/Oの 実 装 アドレスが 異 なるので それを 意 識 してプログラムする ROM RAM I/O I/O I/O 8
仮 想 メモリ 利 点 ユーザープログラムは 実 際 のメモリマップ( 実 装 アドレス 実 装 サイズ)に 依 存 しなくなる 不 連 続 な 物 理 メモリの 断 片 を 連 続 する 仮 想 メモリとして 利 用 できる メモリ 保 護 :バグによって 無 関 係 の 部 分 のメモリが 破 壊 さ れることを 防 止 できる 新 しい 概 念 の 導 入 アドレス 変 換 多 重 メモリ 空 間 デマンドページング 9
仮 想 メモリの 概 念 図 出 典 : フリー 百 科 事 典 ウィキペディア(Wikipedia) 10
アドレス 変 換 仮 想 アドレス 空 間 物 理 アドレス 空 間 ROM MMU アドレスy RAM アドレスx Linux kernel がコントロー ル I/O I/O I/O 11
仮 想 メモリはCPUの 中 だけ 仮 想 アドレス 空 間 物 理 アドレス 空 間 ROM MMU アドレスy RAM アドレスx I/O CPU I/O I/O CPUから 外 にでてくるアドレスバスにのるのは 物 理 アドレスだけ ロジアナでは 仮 想 アドレスは 観 測 できない 12
ユーザープログラムは 仮 想 アドレスだけ 仮 想 アドレス 空 間 物 理 アドレス 空 間 ROM アドレスx CPU MMU アドレスy RAM I/O I/O I/O 物 理 アドレスを 扱 うのはカーネルモードだけ つまりカーネル 本 体 とデバイスドライバ 13
MMUでのアドレス 変 換 31 22 21 12 11 0 仮 想 アドレス Directory Index Page Table Index Page Offset Page Directory Base Register Page Directory Directory Entry Page Table Page Table Entry No page!... page fault Page 物 理 アドレス 14
TLB 仮 想 アドレスページ 物 理 アドレスページ... Translation Lookaside Buffers 仮 想 アドレスをkeyとして 物 理 アドレスを 得 る ハッシュテーブルのようなもの 大 抵 のアドレス 変 換 はTLBにヒットするので 実 際 にPage Directory, Page Tableをアクセ スせずに 済 む 15
多 重 メモリ 空 間 プロセスごとに 独 立 した 仮 想 メモリ 空 間 物 理 アドレス 空 間 ROM RAM I/O I/O 16
デマンドページング ページ 単 位 でマッピングされる ページのサイズはたいていは4Kbytes 2 段 階 で 行 われる 1. 仮 想 メモリの 割 り 当 て(mmap) 管 理 台 帳 に 登 録 するだけ 2. 実 際 にアクセスがあったときに 初 めて そのページに 物 理 メモリが 割 り 当 てられる アクセスのないページには 物 理 メモリが 割 り 当 てられないので 仮 想 メモリサイズ >= 実 際 に 必 要 な 物 理 メモリサイズ 17
デマンドページングの 動 作 例 (1) 仮 想 アドレス 空 間 物 理 アドレス 空 間 read access 対 応 する 物 理 ページが ない! ページフォールト 発 生 カーネルモードへ 18
デマンドページングの 動 作 例 ( 続 ) (2) 仮 想 アドレス 空 間 物 理 アドレス 空 間 マッピング DMA 転 送 カーネルがデータをロードして 物 理 アドレスをマッピングする 19
デマンドページングの 動 作 例 ( 続 ) (3) 仮 想 アドレス 空 間 物 理 アドレス 空 間 data ユーザーモードに 復 帰 ユーザープログラムからは 何 事 もなかったように データが 読 める... でも 実 際 に 時 間 はかかっている 20
ページキャッシュ 物 理 アドレス 空 間 ディスクからの 読 んだ 内 容 はメモリに 余 裕 がある 限 り 保 持 しておく シーケンシャルにアクセスされる 場 合 が 多 いので 数 ページ 分 を まとめて 先 読 みを 行 う そのため(2)では 毎 回 ディスクアクセスが 発 生 するとは 限 らない 21
ページアウト (2)で 物 理 メモリの 空 きがなかった 場 合 使 用 頻 度 の 低 いと 思 われるページを 解 放 する そのページの 内 容 が 変 更 されていなければそのまま 破 棄 変 更 されていればスワップデバイスに 掃 きだす 仮 想 アドレス 空 間 物 理 アドレス 空 間 swap device 掃 きだす ページ ただし 組 込 みLinuxではswap deviceを 装 備 していない ことが 多 い 22
ページアウト( 続 ) 解 放 した 分 のページを 使 って 要 求 されたページの 割 り 当 てを 行 う このような お 手 玉 をすることで 実 際 に 搭 載 されている 物 理 メモリサイズ よりも 大 きなサイズの 仮 想 メモリを 扱 うことができる 仮 想 アドレス 空 間 物 理 アドレス 空 間 DMA 転 送 no page 23
ページの 共 有 仮 想 アドレス 空 間 プロセスA 物 理 アドレス 空 間 プロセスB 同 じファイルの 同 じページは 複 数 の プロセスから 共 有 される Read onlyのページだけでなく write 可 のページも 24
コピーオンライト write access プロセスA Write 可 でプライベートのページに 書 き 込 みが 発 生 すると r/w private ページフォルト 発 生 read only プロセスB 25
コピーオンライト( 続 ) write access プロセスA read/write read only copy プロセスB カーネルはコピーしてページの 設 定 を read/writeに 変 更 する 26
プロセスのメモリ 空 間 0x00000000 process A B C user space 1プロセスあたり 約 3GBのユーザメモリ 空 間... TASK_SIZE 0xffffffff kernel space TASK_SIZEはi386では0xc0000000 ARMでは 0xbf000000 カーネルの 空 間 は 各 プロセスで 共 通 カーネルの 空 間 はユーザーモードでは Read/Write/Execute 不 可 プロセス 切 り 替 えに 伴 ってユーザーメモリ 空 間 が 切 り 替 わる 27
ユーザプロセスのメモリ 空 間 の 実 例 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 r: read device w: write major:minor x: execute s: shared p: private (copy on write) file name 28
ユーザプロセスのメモリ 空 間 の 実 例 ( 詳 細 ) cat /proc/<process_id>/smaps... 0011e000-0024a000 r-xp 00000000 fd:00 15172740 Size: 1200 kb Rss: 136 kb Shared_Clean: 136 kb Shared_Dirty: 0 kb Private_Clean: 0 kb Private_Dirty: 0 kb 0024a000-0024d000 r-xp 0012b000 fd:00 15172740 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 Size: 4 kb Rss: 4 kb Shared_Clean: 0 kb Shared_Dirty: 0 kb Private_Clean: 0 kb Private_Dirty: 4 kb... /lib/libc-2.4.so RSS = 物 理 メモリサイズ /lib/libc-2.4.so /lib/libc-2.4.so 29
システムコール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,... 30
mmapのtips MAP_FIXEDを 指 定 しなければカーネルが 空 いているページをさがしてくれる MAP_FIXEDを 指 定 したときに 既 存 のページ と 重 なっていたら そのページは 内 部 的 に munmapされる なのでこのオプションは 通 常 は 使 用 しない ファイルのオフセットはページサイズの 整 数 倍 でなければならない mmapとmunmapのアドレス サイズは 一 致 していなくてもよい 31
mmapの 使 い 方 (1) 巨 大 サイズのmallocの 代 用 コンパクションなどデータのコピーが 発 生 しない malloc/freeと 違 ってmunmapするときのaddr, size はmmapで 確 保 したときと 異 なっていてもよい まとめて1 回 のmmapで 確 保 して 少 しづつ 分 割 し てmunmapで 返 却 するのもあり glibcのmallocの 実 装 ではある 一 定 以 上 のサイズ のmallocはmmapを 呼 び 出 す DEFAULT_MMAP_THRESHOLD = (128*1024) 32
mmapの 使 い 方 (2) 高 速 なファイルアクセス read, writeのシステムコールでは 内 部 で 物 理 ページにバッファリングしている そこか らユーザの 指 定 した 配 列 にコピーしている mmapを 使 うことで 直 接 ページにアクセスで きるようになるのでデータのコピーを 減 らす ことができる Java1.4の java.nio.mappedbytebuffer 33
mmapの 使 い 方 (3) プロセス 間 の 共 有 メモリ 複 数 のプロセスから 同 じファイルをR/W 可 sharedでマッピングする IPCの 共 有 メモリのシステムコール (shmget, shmat,..)は 内 部 で 同 様 のことを 行 っている 34
mmapの 使 い 方 (4) 物 理 メモリ I/Oポートのアクセス デバイスファイル /dev/mem をマッピング することでユーザーモードで 物 理 メモリ 空 間 をread/writeすることが 可 能 /dev/memをアクセスするにはrootの 権 限 が 必 要 35
まとめ 仮 想 メモリの 使 用 量 と 物 理 メモリの 使 用 量 は 異 なる 実 際 に 問 題 になるのは 物 理 メモリの 使 用 量 仮 想 メモリのオーバーヘッドはいつ 発 生 するのかを 意 識 する TLBミス ページフォルト システムコールmmapの 活 用 36
参 考 文 献 Linux kernel ソース http://www.kernel.org/ GNU C ライブラリのソース http://www.gnu.org/software/libc/ 詳 解 LINUXカーネル 第 2 版 オライリージャパン Linuxカーネル2.6 解 読 室 SoftBank Creative Linux manコマンド その 他 たくさんのWEB 検 索 結 果 37
おまけ: 最 近 の 話 題 CELFのBootTimeResourcesより KernelXIP ApplicationXIP (DataReadInPlace) CELFのMemoryManagementResoucesより Huge/large/superpages Page cache compression 38