web-dev-qa-db-ja.com

共有ライブラリのロードとRAM使用

Linuxが共有ライブラリを管理する方法について疑問に思っています。 (実際には、2009年にリリースされた256MB RAMで動作するDebianベースのディストリビューションであるMaemo Fremantleについて話しています)。

LibQtCore.so.4にリンクし、そのシンボル(クラスと関数を使用)を使用する2つの実行可能ファイルがあるとします。簡単にするために、それらをaおよびbと呼びます。両方の実行可能ファイルが同じライブラリにリンクしていると想定しています。

最初にaを起動します。ライブラリをロードする必要があります。全体として読み込まれますか、それとも必要な部分のみメモリに読み込まれますか(各クラスを使用しないため、使用されるクラスに関するコードのみが読み込まれます)?

次に、bを起動します。 aがまだ実行されていると想定します。 bもlibQtCore.so.4にリンクし、aが使用するクラスの一部を使用しますが、aが使用しないクラスも使用します。ライブラリは二重にロードされますか(aの場合は個別に、bの場合は個別に)?または、すでにRAMにある同じオブジェクトを使用します。 bが新しいシンボルを使用せず、aがすでに実行されている場合、RAMは増加しますか?(または、違いはわずかです)

42
marmistrz

注:私はあなたのマシンにメモリマッピングユニット(MMU)があると仮定します。 MMUを必要としないLinuxバージョン(µClinux)があり、この回答はそこでは適用されません。

MMUとは?それはハードウェア —プロセッサやメモリコントローラの一部。共有ライブラリのリンクを理解するには、MMUの仕組みを正確に理解する必要はありません。MMUでlogicalメモリアドレス(プログラムで使用されるアドレス)およびphysicalメモリアドレス(実際にメモリバス上に存在するアドレス)メモリは、 Linuxでは通常4Kのサイズのページです。4Kページの場合、論理アドレス0〜4095はページ0、論理アドレス4096〜8191はページ1などです。MMUはこれらの物理ページにマップしますRAM、および各論理ページは通常0または1の物理ページにマップできます。特定の物理ページは複数の論理ページに対応できます(これがメモリの共有方法です。複数の論理ページが同じ物理ページに対応しています)。これは関係なく適用されますOSの;それはハードウェアの説明です。

プロセススイッチでは、カーネルがMMUページマッピングを変更するため、各プロセスには独自のスペースがあります。プロセス1000のアドレス4096は、プロセス1001のアドレス4096と完全に異なる場合があります(通常は異なります)。 。

ほとんどの場合、アドレスは論理アドレスです。ユーザー空間プログラムは、物理アドレスをほとんど扱いません。

現在、ライブラリを構築する方法もいくつかあります。プログラムがライブラリの関数foo()を呼び出すとしましょう。 CPUはシンボルや関数呼び出しについて何も認識していません。論理アドレスにジャンプし、そこで見つけたコードを実行する方法を知っているだけです。これを行うにはいくつかの方法があります(ライブラリが独自のグローバルデータにアクセスする場合などにも同様のことが当てはまります)。

  1. 呼び出す論理アドレスをハードコードすることができます。これには、ライブラリが常に同じをまったく同じ論理アドレスでロードする必要があります。 2つのライブラリが同じアドレスを必要とする場合、動的リンクが失敗し、プログラムを起動できません。ライブラリは他のライブラリを必要とする場合があるため、基本的に、システム上のすべてのライブラリに一意の論理アドレスが必要です。しかし、それが機能すれば、非常に高速です。 (これは、a.outがどのように処理を行ったか、およびプリリンクが行う設定の種類です)。
  2. 偽の論理アドレスをハードコードし、ライブラリをロードするときに動的リンカーに適切なアドレスで編集するように指示する可能性があります。これは、ライブラリーのロード時にかなりの時間を要しますが、その後は非常に高速です。
  3. それは間接層を追加することができます: CPUレジスタ を使用して、ライブラリがロードされる論理アドレスを保持し、そのレジスタからのオフセットとしてすべてにアクセスします。これにより、各アクセスにパフォーマンスコストがかかります。

少なくとも汎用システムでは、だれも#1をもう使用していません。 32ビットシステムでは一意の論理アドレスリストを維持することは不可能で(回避するのに十分ではありません)、64ビットシステムでは管理上の悪夢になります。ただし、事前リンクは、システムごとに行われます。

#2と#3のどちらを使用するかは、ライブラリがGCCの-fPIC(位置独立コード)オプションでビルドされているかどうかによって異なります。 #2はなし、#3はあり。通常、ライブラリは-fPICを使用して構築されるため、#3が実行されます。

詳細については、Ulrich Drepperの 共有ライブラリの作成方法(PDF) を参照してください。

最後に、あなたの質問に答えることができます:

  1. ライブラリがwith-fPIC(ほぼ確実にそうである)で構築されている場合、ページの大部分はすべてのプロセスでまったく同じですそれをロードします。プロセスabは、ライブラリを異なる論理アドレスでロードする可能性がありますが、これらは同じ物理ページをポイントします。メモリは共有されます。さらに、RAMのデータはディスク上のデータと正確に一致するため、ページフォールトハンドラーが必要な場合にのみロードできます。
  2. ライブラリがなし-fPICで構築されている場合、ライブラリのほとんどのページでリンクの編集が必要であり、異なることがわかります。したがって、それらは別々の物理ページでなければなりません(異なるデータが含まれているため)。つまり、共有されていません。ページがディスク上のものと一致しないので、ライブラリ全体がロードされても驚かないでしょう。もちろん、後で(スワップファイルで)ディスクにスワップアウトすることもできます。

pmapツールを使用して、または/procのさまざまなファイルを直接チェックして、これを調べることができます。たとえば、次は、2つの異なる新しく生成されたbcsでのpmap -xの(部分的な)出力です。 pmapによって表示されるアドレスは、通常、論理アドレスであることに注意してください。

pmap -x 14739
Address           Kbytes     RSS   Dirty Mode  Mapping
00007f81803ac000     244     176       0 r-x-- libreadline.so.6.2
00007f81803e9000    2048       0       0 ----- libreadline.so.6.2
00007f81805e9000       8       8       8 r---- libreadline.so.6.2
00007f81805eb000      24      24      24 rw--- libreadline.so.6.2


pmap -x 17739
Address           Kbytes     RSS   Dirty Mode  Mapping
00007f784dc77000     244     176       0 r-x-- libreadline.so.6.2
00007f784dcb4000    2048       0       0 ----- libreadline.so.6.2
00007f784deb4000       8       8       8 r---- libreadline.so.6.2
00007f784deb6000      24      24      24 rw--- libreadline.so.6.2

ライブラリが複数の部分にロードされていることがわかります。pmap -xは、それぞれの詳細を個別に提供します。 2つのプロセス間で論理アドレスが異なることがわかります。あなたはそれらが同じであると合理的に期待します(同じプログラムが実行され、コンピューターは通常そのように予測できるため)が、意図的にそれらをランダム化する address space layout randomization と呼ばれるセキュリティ機能があります。

サイズ(Kバイト)と常駐サイズ(RSS)の違いから、ライブラリセグメント全体がロードされていないことがわかります。最後に、より大きなマッピングの場合、dirtyは0であることがわかります。これは、ディスク上のものに正確に対応していることを意味します。

pmap -XXを使用して再実行すると、-XX出力はカーネルバージョンによって異なるため、実行中のカーネルバージョンに応じて、最初のマッピングがShared_Clean 176、これはRSSと完全に一致します。 Sharedメモリは、物理ページが複数のプロセス間で共有されることを意味します。これはRSSと一致するため、メモリ内のすべてのライブラリが共有されることを意味します(共有と共有の詳細については、以下の「関連項目」を参照してください)。民間):

pmap -XX 17739
         Address Perm   Offset Device   Inode  Size  Rss Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous AnonHugePages Swap KernelPageSize MMUPageSize Locked                   VmFlagsMapping
    7f784dc77000 r-xp 00000000  fd:00 1837043   244  176  19          176            0             0             0        176         0             0    0              4           4      0       rd ex mr mw me sd  libreadline.so.6.2
    7f784dcb4000 ---p 0003d000  fd:00 1837043  2048    0   0            0            0             0             0          0         0             0    0              4           4      0             mr mw me sd  libreadline.so.6.2
    7f784deb4000 r--p 0003d000  fd:00 1837043     8    8   8            0            0             0             8          8         8             0    0              4           4      0       rd mr mw me ac sd  libreadline.so.6.2
    7f784deb6000 rw-p 0003f000  fd:00 1837043    24   24  24            0            0             0            24         24        24             0    0              4           4      0    rd wr mr mw me ac sd  libreadline.so.6.2


関連項目

57
derobert