Memory

載入共享庫和 RAM 使用情況

  • March 24, 2014

我想知道 Linux 管理共享庫的方式。(實際上我說的是 Maemo Fremantle,2009 年發布的基於 Debian 的發行版,執行在 256MB RAM 上)。

假設我們有兩個執行檔連結到 libQtCore.so.4 並使用它的符號(使用它的類和函式)。為簡單起見,我們稱它們為aand 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 個物理頁。一個給定的物理頁面可以對應多個邏輯頁面(這就是記憶體的共享方式:多個邏輯頁面對應同一個物理頁面)。請注意,無論作業系統如何,這都適用;這是對硬體的描述。

在程序切換時,核心會更改 MMU 頁面映射,以便每個程序都有自己的空間。程序 1000 中的地址 4096 可以(並且通常是)與程序 1001 中的地址 4096 完全不同。

幾乎每當你看到一個地址時,它就是一個邏輯地址。使用者空間程序幾乎從不處理物理地址。

現在,也有多種方法可以建構庫。假設一個程序呼叫foo()庫中的函式。CPU 對符號或函式呼叫一無所知——它只知道如何跳轉到邏輯地址,並執行它找到的任何程式碼。有幾種方法可以做到這一點(當圖書館訪問自己的全域數據時,類似的事情也適用):

  1. 它可以硬編碼一些邏輯地址來呼叫它。這要求庫始終載入到完全相同的邏輯地址。如果兩個庫需要相同的地址,動態連結將失敗,您將無法啟動程序。庫可能需要其他庫,因此這基本上要求系統上的每個庫都具有唯一的邏輯地址。但是,如果它有效,它會非常快。(這就是 a.out 做事的方式,以及預連結所做的那種設置)。
  2. 它可以硬編碼一個虛假的邏輯地址,並告訴動態連結器在載入庫時編輯正確的地址。這在載入庫時會花費相當多的時間,但之後速度非常快。
  3. 它可以添加一個間接層:使用CPU 寄存器來保存載入庫的邏輯地址,然後以該寄存器的偏移量訪問所有內容。這對每次訪問都造成了性能成本。

幾乎沒有人再使用 #1 了,至少在通用系統上沒有。保持唯一的邏輯地址列表在 32 位系統上是不可能的(沒有足夠的餘地),而在 64 位系統上是管理的噩夢。不過,預連結是在每個系統的基礎上執行此操作的。

是否使用 #2 或 #3 取決於庫是否使用 GCC -fPIC(位置無關程式碼)選項建構。#2 沒有,#3 有。通常,庫是用 建構的-fPIC,所以會發生 #3。

有關更多詳細資訊,請參閱 Ulrich Drepper 的如何編寫共享庫 (PDF)

所以,最後,你的問題可以得到回答:

  1. 如果庫是 -fPIC(幾乎可以肯定應該是)建構的,那麼絕大多數頁面對於載入它的每個程序都是完全相同的。您的程序ab可能會在不同的邏輯地址載入庫,但這些將指向相同的物理頁面:記憶體將被共享。此外,RAM 中的數據與磁碟上的數據完全匹配,因此只有在頁面錯誤處理程序需要時才能載入它。
  2. 如果庫是在沒有 的情況下建構的**,** -fPIC那麼庫的大多數頁面都需要連結編輯,並且會有所不同。因此,它們必須是單獨的物理頁面(因為它們包含不同的數據)。這意味著它們不共享。這些頁面與磁碟上的內容不匹配,因此如果載入了整個庫,我不會感到驚訝。它當然可以隨後被換出到磁碟(在交換文件中)。

您可以使用該pmap工具進行檢查,也可以直接通過檢查/proc. 例如,這是pmap -x兩個不同新生成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分別為您提供每個部分的詳細資訊。您會注意到兩個程序之間的邏輯地址不同;您可以合理地期望它們是相同的(因為它執行相同的程序,並且電腦通常可以這樣預測),但是有一個稱為地址空間佈局隨機化的安全功能可以故意隨機化它們。

從大小(Kbytes)和駐留大小(RSS)的差異可以看出,整個庫段還沒有被載入。最後,您可以看到對於較大的映射,dirty 為 0,這意味著它與磁碟上的內容完全對應。

您可以使用 重新執行pmap -XX,它會根據您正在執行的核心版本向您顯示 -XX 輸出因核心版本而異 - 第一個映射的 aShared_Clean為 176,與RSS. Sharedmemory 意味著物理頁面在多個程序之間共享,並且由於它與 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

也可以看看

引用自:https://unix.stackexchange.com/questions/116327