第59章 Linux の仮想メモリーエリア・メモリー記述子

 ファイル関係のオブジェクトについては一通り説明しましたね。

 では次は Linux のメモリーの構成について軽く説明していきたいと思います。

 このメモリー領域( memory region )は Linux ではプロセスアドレス空間のセグメント(テキスト、スタック、データ、BSS等)としても定義することがあります。

 その際に使われるのが以下のオブジェクトです。

struct mm_struct
一つのプロセスに対して一つあるメモリー空間を抽象化したオブジェクト。
struct vm_area_struct
mm_struct の部品、メモリー領域を定義するオブジェクト。
struct address_space
ページキャッシュ内のページのグループ化、管理に使われるオブジェクト。ファイルをプロセスアドレス空間に紐付ける(マッピングする)のに使われる。

 ファイルメモリーマッピングを使うための機構は 3 つにわけられます。

 最初のメモリー記述子は struct mm_struct に該当し、次の仮想メモリーエリアは struct vm_area_struct に該当します。

 プロセスアドレス空間、ファイル、ブロックデバイスを統合管理したページキャッシュのオブジェクトが struct address_space みたいな感じです。

 まあ、ここら辺は自信ニキじゃないんですがね… (´・ω・`)

 mm_struct と vm_area_struct の関係は以下のようなポインターの依存図で表すことができます。

img/vma_struct.png

 まずメモリー記述子である mm_struct から vm_area_struct の先頭を指し、それが次の vm_area_struct オブジェクトを指すポインターを持ちます。

 vm_area_struct は線形アドレス空間にマップされます。

 次により詳細を見ると以下のように

img/task_struct_to_vma.png

 この図で分かるとおり mm_struct には mmap というポインターがあり、これが vm_area_sturct を指しています。

 また vm_area_struct には vm_next というポインターによって他の vm_area_struct オブジェクトと連結されています。

 vm_file は file オブジェクトを指すポインターであり、ファイルマッピングをする際に使われます。

 後はマップされたプロセスアドレス空間の領域の開始アドレスと終了アドレスを持っています。

 Linux 上でこれを確かめたいなら以下のように /proc/self/maps の中身を表示させるだけです。

$ sudo cat /proc/self/maps
55db82bc1000-55db82bc9000 r-xp 00000000 08:01 37486617                   /bin/cat
55db82dc8000-55db82dc9000 r--p 00007000 08:01 37486617                   /bin/cat
55db82dc9000-55db82dca000 rw-p 00008000 08:01 37486617                   /bin/cat
55db8451c000-55db8453d000 rw-p 00000000 00:00 0                          [heap]
7fe9b5272000-7fe9b5d41000 r--p 00000000 08:01 90053152                   /usr/lib/locale/locale-archive
7fe9b5d41000-7fe9b5f28000 r-xp 00000000 08:01 25563707                   /lib/x86_64-linux-gnu/libc-2.27.so
7fe9b5f28000-7fe9b6128000 ---p 001e7000 08:01 25563707                   /lib/x86_64-linux-gnu/libc-2.27.so
7fe9b6128000-7fe9b612c000 r--p 001e7000 08:01 25563707                   /lib/x86_64-linux-gnu/libc-2.27.so
7fe9b612c000-7fe9b612e000 rw-p 001eb000 08:01 25563707                   /lib/x86_64-linux-gnu/libc-2.27.so
7fe9b612e000-7fe9b6132000 rw-p 00000000 00:00 0
7fe9b6132000-7fe9b6159000 r-xp 00000000 08:01 25563679                   /lib/x86_64-linux-gnu/ld-2.27.so
7fe9b6315000-7fe9b6339000 rw-p 00000000 00:00 0
7fe9b6359000-7fe9b635a000 r--p 00027000 08:01 25563679                   /lib/x86_64-linux-gnu/ld-2.27.so
7fe9b635a000-7fe9b635b000 rw-p 00028000 08:01 25563679                   /lib/x86_64-linux-gnu/ld-2.27.so
7fe9b635b000-7fe9b635c000 rw-p 00000000 00:00 0
7ffc7d39f000-7ffc7d3c0000 rw-p 00000000 00:00 0                          [stack]
7ffc7d3ef000-7ffc7d3f2000 r--p 00000000 00:00 0                          [vvar]
7ffc7d3f2000-7ffc7d3f4000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

 高いアドレスに stack とか書いてますね。

 7ffc7d39f000-7ffc7d3c0000 がスタック領域のアドレス範囲ってことです。

 それとヒープ領域は 55db8451c000-55db8453d000 となりますね。

 ちなみにメモリーレイアウトについては malloc や sbrk 等のメモリー割り当ての説明に使った図を再度見直していただけば分かるんじゃないでしょうかね?

img/process_address_space_brk.png

 32 ビットなので 64 ビットのアドレスとは桁が違いますが /proc/self/maps の結果と比較していくと分かりみがあると思います。

Copyright 2018-2019, by Masaki Komatsu