
Linuxシステムで共有ライブラリをロードすると、共有ライブラリのメモリレイアウトはどうなりますか?
たとえば、元のメモリレイアウトは次のようになります。
+-----------+
|heap(ori) |
+-----------+
|stack(ori) |
+-----------+
|.data(ori) |
+-----------+
|.text(ori) |
+-----------+
dlopenを行うときのfoo.so
メモリレイアウトはAですか、それともBですか?
A
+-----------+
|heap(ori) |
+-----------+
|stack(ori) |
+-----------+
|.data(ori) |
+-----------+
|.text(ori) |
+-----------+
|heap(foo) |
+-----------+
|stack(foo) |
+-----------+
|.data(foo) |
+-----------+
|.text(foo) |
+-----------+
または
B
+-----------+
|heap(ori) |
+-----------+
|heap(foo) |
+-----------+
|stack(foo) |
+-----------+
|stack(ori) |
+-----------+
|.data(foo) |
+-----------+
|.data(ori) |
+-----------+
|.text(foo) |
+-----------+
|.text(ori) |
+-----------+
それともAとB以外に何かがあるのでしょうか?
答え1
答えは「その他」です。メモリレイアウトを理解するために使用できますcat /proc/self/maps
。私の64ビットArchノートブックから:
00400000-0040c000 r-xp 00000000 08:02 1186758 /usr/bin/cat
0060b000-0060c000 r--p 0000b000 08:02 1186758 /usr/bin/cat
0060c000-0060d000 rw-p 0000c000 08:02 1186758 /usr/bin/cat
02598000-025b9000 rw-p 00000000 00:00 0 [heap]
7fe4b805c000-7fe4b81f5000 r-xp 00000000 08:02 1182914 /usr/lib/libc-2.21.so
7fe4b81f5000-7fe4b83f5000 ---p 00199000 08:02 1182914 /usr/lib/libc-2.21.so
7fe4b83f5000-7fe4b83f9000 r--p 00199000 08:02 1182914 /usr/lib/libc-2.21.so
7fe4b83f9000-7fe4b83fb000 rw-p 0019d000 08:02 1182914 /usr/lib/libc-2.21.so
7fe4b83fb000-7fe4b83ff000 rw-p 00000000 00:00 0
7fe4b83ff000-7fe4b8421000 r-xp 00000000 08:02 1183072 /usr/lib/ld-2.21.so
7fe4b85f9000-7fe4b85fc000 rw-p 00000000 00:00 0
7fe4b85fe000-7fe4b8620000 rw-p 00000000 00:00 0
7fe4b8620000-7fe4b8621000 r--p 00021000 08:02 1183072 /usr/lib/ld-2.21.so
7fe4b8621000-7fe4b8622000 rw-p 00022000 08:02 1183072 /usr/lib/ld-2.21.so
7fe4b8622000-7fe4b8623000 rw-p 00000000 00:00 0
7ffe430c4000-7ffe430e5000 rw-p 00000000 00:00 0 [stack]
7ffe431ed000-7ffe431ef000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
実行可能ファイルが低いメモリ、つまり.textセグメント、読み取り専用データ、および.bssにロードされることがわかります。これが「ヒップ」です。より高いメモリには、Cライブラリと「ELFファイルインタプリタ」、「ld-so」がロードされます。それにはスタックがあります。指定されたアドレス空間に対してどのくらいの共有ライブラリがロードされても、スタックとヒープは1つしかありません。cat
Cライブラリだけがロードされているようです。
これにより、cat /proc/$$/maps
呼び出したシェルのメモリマップを取得できますcat
。すべてのシェルには動的にロードされる多数のライブラリがあり、多数のライブラリがロードされzsh
ますbash
。 「[ヒップ]」と「[スタック]」が1つしかないことがわかります。
呼び出されると、dlopen()
共有オブジェクトファイルはより高いアドレスのアドレス空間にマッピングされます/usr/lib/libc-2.21.so
。mmap()
返されたすべてのアドレスが表示される「実装に応じた」メモリマップセグメントがあります。バラよりインメモリプログラム分析良いグラフィックのために。
ソースが/usr/lib/ld-2.21.so
少しトリッキーですが、2等市民ではありませんdlopen()
。dlopen()
「vdso」と「vsyscall」は少し不思議ですがこのStackoverflowの質問良い説明があり、Wikipediaにも説明があります。