Paylaşılan kütüphanelerin yüklenmesi ve RAM kullanımı


40

Linux'un paylaşılan kütüphaneleri nasıl yönettiğini merak ediyorum. (Aslında 2009'da 256 MB RAM'de çalışan Debian merkezli bir dağıtım olan Maemo Fremantle'den bahsediyorum).

Diyelim ki libQtCore.so.4 ile bağlantılı ve sembollerini kullanan (sınıflarını ve işlevlerini kullanarak) iki çalıştırılabilir dosyamız var. Sadelik uğruna onları ave arayalım b. Her iki çalıştırıcının da aynı kütüphanelere bağlandığını varsayıyoruz.

İlk önce fırlatıyoruz a. Kütüphanenin yüklenmesi gerekiyor. Tamamen yüklenmiş mi yoksa sadece gerekli olan kısımda belleğe mi yüklenmiştir (her sınıfı kullanmadığımız için, yalnızca kullanılan sınıflarla ilgili kod yüklenir)?

Sonra fırlatırız b. Bunun ahala çalışıyor olduğunu varsayıyoruz . blibQtCore.so.4 ile de bağlantı kurar ve kullanılan bazı sınıfları a, ancak aynı zamanda kullanmadıklarını kullanır a. Kütüphane çift yüklü olacak mı (ayrı ayrı ave ayrı ayrı b)? Yoksa aynı nesneyi zaten RAM'de mi kullanacaklar? Eğer bkullanımları yeni semboller ve azaten çalışıyor paylaşılan kütüphaneler tarafından RAM kullanılan olacak artırmak? (Yoksa fark önemsiz olacak)

Yanıtlar:


53

NOT: Makinenizde bir bellek eşleme birimi (MMU) olduğunu varsayacağım. MMU gerektirmeyen bir Linux sürümü (µClinux) vardır ve bu cevap burada geçerli değildir.

MMU nedir? Donanım , işlemcinin ve / veya bellek denetleyicinin bir parçası. Paylaşılan kütüphane bağlantısının anlaşılması, bir MMU’nun tam olarak nasıl çalıştığını anlamanızı gerektirmez, sadece bir MMU’nun mantıksal bellek adresleri (programlar tarafından kullanılanlar) ve fizikselhafıza adresleri (aslında hafıza yolunda bulunanlar). Bellek sayfalara ayrılır, tipik olarak Linux'ta 4K boyutundadır. 4k sayfalarda, mantıksal adresler 0-4095, sayfa 0, mantıksal adresler 4096–8191, sayfa 1'dir, vb. Belirli bir fiziksel sayfa birden fazla mantıksal sayfaya karşılık gelebilir (bu, hafızanın paylaşılma şeklidir: birden fazla mantıksal sayfa aynı fiziksel sayfaya karşılık gelir). Bunun işletim sistemi ne olursa olsun geçerli olduğuna dikkat edin; bu donanımın açıklaması.

İşlem geçişinde, çekirdek MMU sayfa eşlemelerini değiştirir, böylece her işlem kendi alanına sahip olur. İşlem 1000'deki adres 4096, işlem 1001'deki adres 4096'dan tamamen farklı olabilir (ve genellikle de).

Ne zaman bir adres görseniz, mantıklı bir adres. Kullanıcı alanı programları neredeyse hiç fiziksel adreslerle uğraşmaz.

Şimdi, kütüphaneler oluşturmanın birçok yolu var. Diyelim ki bir program foo()kütüphanedeki işlevi çağırıyor . CPU, semboller hakkında hiçbir şey bilmez veya fonksiyon çağrıları gerçektir - sadece mantıksal bir adrese nasıl atlayacağını bilir ve orada hangi kodu bulursa uygular. Bunu yapabilmesinin birkaç yolu vardır (ve bir kütüphane kendi küresel verilerine vb. Eriştiğinde benzer şeyler de geçerlidir):

  1. Aramak için bazı mantıksal adresleri zor kodlayabilir. Bu, kütüphanenin daima aynı mantıksal adrese yüklenmesini gerektirir . İki kitaplık aynı adresi gerektiriyorsa, dinamik bağlantı başarısız olur ve programı başlatamazsınız. Kütüphaneler başka kütüphaneler gerektirebilir, bu nedenle sistemdeki her kütüphanenin benzersiz mantıksal adreslere sahip olmasını gerektirir. İşe yararsa, çok hızlı. (Bu nasıl bir şeyler yaptığını ve ön planlamanın yaptığı türden bir şeydi).
  2. Sahte bir mantıksal adresi zor kodlayabilir ve kütüphaneye yüklerken dinamik linker'a uygun olanı düzenlemesini söyler. Bu, kütüphaneleri yüklerken çok zaman alır, ancak bundan sonra çok hızlıdır.
  3. Bir aktarım katmanı ekleyebilir: kütüphanenin yüklendiği mantıksal adresi tutmak için bir CPU kaydı kullanın ve ardından her şeye bu kayıttan ofset olarak erişin. Bu, her erişim için bir performans maliyeti getirir.

Neredeyse hiç kimse artık # 1'i kullanmıyor, en azından genel amaçlı sistemlerde. Bu benzersiz mantıksal adres listesini tutmak, 32-bit sistemlerde (dolaşmak için yeterli değil) ve 64-bit sistemlerde idari bir kabus için imkansızdır. Önceden linkleme bu tür, ancak, sistem bazında yapar.

# 2 veya # 3'ün kullanılıp kullanılmadığı, kütüphanenin GCC'nin -fPIC(konum bağımsız kodu) seçeneğiyle oluşturulmuş olmasına bağlıdır . # 2 yok, # 3 var. Genel olarak, kütüphaneler inşa edilmiştir -fPIC, yani # 3 olan şey budur.

Daha fazla ayrıntı için Ulrich Drepper'ın Paylaşılan Kütüphaneleri Nasıl Yazacağını görün (PDF) .

Böylece, nihayet, sorunuz cevaplanabilir:

  1. Kütüphane inşa edilirse ile -fPIC (neredeyse kesinlikle olması gerektiği gibi), sayfaların büyük çoğunluğu her işlem için tam yükleri öyle aynıdır. İşlemleriniz ave bkitaplığı farklı mantıksal adreslere yerleştirebilirsiniz, ancak bunlar aynı fiziksel sayfalara işaret eder: bellek paylaşılır. Ayrıca, RAM'deki veriler diskteki ile tam olarak eşleşir, bu nedenle sadece sayfa arıza işleyicisi tarafından gerektiğinde yüklenebilir.
  2. Kitaplık olmadan -fPIC oluşturulmuşsa, kitaplığın çoğu sayfasının bağlantı düzenlemelerine ihtiyaç duyacağı ve farklı olacağı anlaşılmaktadır. Bu nedenle, fiziksel sayfalar ayrı olmalıdır (farklı veriler içerdiklerinden). Bu, paylaşılmadıkları anlamına gelir. Sayfalar diskte olanlarla eşleşmiyor, bu yüzden kütüphanenin tamamı yüklendiyse şaşırmam. Elbette daha sonra diske (takas dosyasında) değiştirilebilir.

Bunu pmaparaçla veya içinde çeşitli dosyaları kontrol ederek doğrudan inceleyebilirsiniz /proc. Örneğin, burada pmap -xiki farklı yeni ortaya çıkmış ürünün bir (kısmi) çıktısı var bc. Pmap ile gösterilen adreslerin tipik olarak mantıksal adresler olduğunu unutmayın:

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

Kütüphanenin birden fazla bölüme yüklendiğini görebilirsiniz ve pmap -xher biri için ayrı ayrı bilgi verir. Mantıksal adreslerin iki işlem arasında farklı olduğunu fark edeceksiniz; Bunların aynı olmalarını makul bir şekilde beklersiniz (aynı program çalıştığından ve bilgisayarlar genellikle bunun gibi tahmin edilebilir olduğundan), ancak onları kasıtlı olarak rasgele konumlandıran adres alanı düzeni rastgeleştirme adı verilen bir güvenlik özelliği vardır.

Boyuttaki (Kbayt) ve yerleşik boyuttaki (RSS) farkın tamamını, tüm kitaplık segmentinin yüklenmediğini görebilirsiniz. Son olarak, daha büyük eşlemeler için kirli olanın 0 olduğunu, yani diskteki ile tam olarak aynı olduğunu görebilirsiniz.

Yeniden çalıştırabilirsiniz pmap -XXve size gösterecektir - çalıştırmakta olduğunuz çekirdek sürümüne bağlı olarak, -XX çıktısı çekirdek sürümüne göre değiştiğinden - ilk eşlemenin Shared_Cleantam olarak eşleşen 176 değerine sahip olduğunu gösterir RSS. Sharedbellek, fiziksel sayfaların birden fazla işlem arasında paylaşıldığı ve RSS ile eşleştiği anlamına gelir; bu, bellekteki tüm kitaplığın paylaşıldığı anlamına gelir (paylaşılan ve özel bilgilerin daha fazla açıklanması için Ayrıca Ayrıca Bkz.

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


Ayrıca bakınız


Bu, önyüklemenin artık bir faydası olmadığı anlamına gelir (ve -fPICkullanım bir süre önce tamamen değişmiştir).
Hauke,

@crisron Düzeltmeler için teşekkürler. Bilginize, Markdown sizin için sayar - benim tekrarlanan işlenmiş çıktı 1. doğru. Ayrıca, yaptığınız şeyde birkaç değişiklik yaptım - "başlangıç ​​adresi" teknik jargondur, muhtemelen ortada "mantıksal" ifadesiyle karışıklığa neden oldum. Jargondan kurtulmak için değiştirdim. Ayrıca, sayfalar bu adreslere eşdeğerdir, AFAIK bu adreslerin hiç farklı bir sayfa olması mümkün değildir. Tekrar denedim, siparişi değiştirdim, umarım daha açıktır.
derobert

kahretsin, şimdi bu bir cevap !!!
Evan Carroll
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.