2017-07-19 14 views
-2

Linuxが共有ライブラリを読み込むとき、私の理解では、テキストセクションは物理メモリに一度だけロードされ、それを参照する別のプロセスのページテーブルにマップされます。共有ライブラリテキストセクションの複数のコピーは、どのようにして物理メモリ内で回避されますか?

しかし、/ whoは、同じ共有ライブラリのテキストセクションが物理メモリに複数回ロードされていないことを確認/確認します。

ローダやmmap()システムコールによって重複が回避されるのでしょうか、それとも他の方法や方法がありますか?

Edit1: これまでに行われたこと(研究)を示しているに違いありません。ここにあります...

シンプルスリープコマンドをトレースしようとしました。

$ strace sleep 100 & 
[1] 22824 
$ execve("/bin/sleep", ["sleep", "100"], [/* 26 vars */]) = 0 
brk(0)         = 0x89bd000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY)  = 3 
fstat64(3, {st_mode=S_IFREG|0644, st_size=92360, ...}) = 0 
mmap2(NULL, 92360, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f56000 
close(3)        = 0 
open("/lib/libc.so.6", O_RDONLY)  = 3 
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0`G\0004\0\0\0"..., 512) = 512 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f55000 
fstat64(3, {st_mode=S_IFREG|0755, st_size=1706232, ...}) = 0 
mmap2(0x460000, 1426884, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x460000 
mmap2(0x5b7000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x156) = 0x5b7000 
mmap2(0x5ba000, 9668, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x5ba000 
close(3)        = 0 
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f54000 
... 
munmap(0xb7f56000, 92360)    = 0 
... 

このプロセスの/ proc/pid/mapsファイルを確認してください。

$ cat /proc/22824/maps 
00441000-0045c000 r-xp 00000000 fd:00 2622360 /lib/ld-2.5.so 
... 
00460000-005b7000 r-xp 00000000 fd:00 2622361 /lib/libc-2.5.so 
... 
00e3e000-00e3f000 r-xp 00e3e000 00:00 0   [vdso] 
08048000-0807c000 r-xp 00000000 fd:00 5681559 /usr/bin/strace 
... 

は、ここでは、 PROT_READ|PROT_EXECとlibc.so.6とのmmap2ためaddr引数は()特定のアドレスにあったことが分かりました。これにより、物理メモリ内の共有ライブラリマッピングがローダーによって何らかの形で管理されていると私は考えていました。

+0

この質問に関連するすべての関連システムと同様に、Linuxカーネルは、ソースが閲覧可能なオープンソースです。 –

+0

@Someprogrammerdudeそれは本当ですが、カーネルでこれをチェックすることができる人は、ずっと前にそれを学んだことがあります。 – peterh

答えて

0

共有ライブラリはmmap()システムコールによってロードされ、Linuxカーネルはスマートです。これには内部データ構造があり、ファイル記述子(マウントインスタンスとiノード番号を含む)をマップされたページにマップします。

ダイナミックリンカ(そのコードは/lib/ld-linux.soなど)は、このmmap()コールを使用してライブラリをマップしてからシンボルテーブルを再配置します。このページレベルの重複排除は、完全にカーネルによって行われます。

マッピングにはPROT_READ|PROT_EXEC|PROT_SHAREDフラグが使用されます。これはどのツールでも簡単に確認できます(strace /bin/echoなど)。

+0

ファイルディスクリプタとiノード番号への参照は私が探していたものでした。ありがとう – emilk

+0

私の喜び:-)答えがあなたの問題を解決した場合は、左側のパイプアイコンをクリックして回答を受け入れることができます。これは回答者の報酬であり、問​​題が既に解決されていることを将来の訪問者に示します。 – peterh

関連する問題