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):
- 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).
- 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.
- 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:
- 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 a
ve b
kitaplığı 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.
- 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 pmap
araçla veya içinde çeşitli dosyaları kontrol ederek doğrudan inceleyebilirsiniz /proc
. Örneğin, burada pmap -x
iki 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 -x
her 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 -XX
ve 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_Clean
tam olarak eşleşen 176 değerine sahip olduğunu gösterir RSS
. Shared
bellek, 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
-fPIC
kullanım bir süre önce tamamen değişmiştir).