GNU/Linux >> Linux の 問題 >  >> Linux

共有ライブラリのロードと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は増加しますか? (または、違いは重要ではありません)

承認された回答:

注:お使いのマシンにはメモリマッピングユニット(MMU)があると想定します。 MMUを必要としないLinuxバージョン(µClinux)があり、この回答はそこには当てはまりません。

MMUとは何ですか?それはハードウェアであり、プロセッサやメモリコントローラの一部です。共有ライブラリのリンクを理解するために、MMUがどのように機能するかを正確に理解する必要はありません。ただ、MMUによって論理の間に違いが生じる可能性があります。 メモリアドレス(プログラムで使用されるアドレス)と物理 メモリアドレス(メモリバスに実際に存在するアドレス)。メモリはページに分割されます。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レジスタを使用してライブラリがロードされる論理アドレスを保持し、そのレジスタからのオフセットとしてすべてにアクセスします。これにより、各アクセスにパフォーマンスコストがかかります。
関連:Linux – cpはファイルのメタデータを失いますか?

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

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

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

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

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

これはpmapで調べることができます ツール、または/proc内のさまざまなファイルを直接チェックする 。たとえば、これはpmap -xの(部分的な)出力です。 2つの異なる新しく生成されたbc s。 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つのプロセス間で論理アドレスが異なることに気付くでしょう。それらは同じであると合理的に期待できますが(同じプログラムが実行されており、コンピューターは通常そのように予測可能であるため)、意図的にランダム化するアドレス空間配置のランダム化と呼ばれるセキュリティ機能があります。

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

pmap -XXを使用して再実行できます 、そして、実行しているカーネルのバージョンに応じて、-XX出力はカーネルのバージョンによって異なるため、最初のマッピングにShared_Cleanがあることが示されます。 RSSと完全に一致する176の 。 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

関連項目

  • プロセスのメモリ使用量に関する情報を/proc/ pid / smapsから取得して、クリーン/ダーティ共有/プライベート全体の説明を取得します。
関連:Linux –前日にsarを表示させる方法は?
Linux
  1. プログラムのRAM使用量を測定しますか?

  2. Linux 共有ライブラリの紹介 (共有ライブラリの作成方法)

  3. Linux で共有ライブラリを初期化する方法

  1. Linux 共有ライブラリのストリッピング

  2. バージョン情報を共有ライブラリとバイナリに埋め込む方法は?

  3. libstdc++.so.5:共有オブジェクト ファイルを開けません - ただし、ライブラリはインストールされており、最新です

  1. 共有オブジェクト (.so)、静的ライブラリ (.a)、および DLL (.so) の違いは?

  2. 共有ライブラリの読み込み中にエラーが発生しました:libncurses.so.5:

  3. 共有ライブラリの読み込みエラー (glew)