SO (paylaşılan nesne) sayıları nasıl çalışır?


123

Linux altındaki paylaşılan nesnelerin "sayılar" kullandığını, yani paylaşılan nesnenin farklı sürümlerine farklı uzantılar verildiğini biliyorum, örneğin:

  • example.so.1
  • example.so.2

Anladığım kadarıyla, bir kütüphanede iki sürümün bir sistemde bulunabileceği (Windows'taki "DLL Hell" in aksine) iki ayrı dosyaya sahip olmak olduğunu biliyorum. Bunun pratikte nasıl çalıştığını bilmek ister misiniz? Çoğu zaman bunun example.soaslında en son sürümün example.so.2nerede .2olduğuna dair sembolik bir bağlantı olduğunu görüyorum . Öyleyse, daha eski bir sürüme bağlı olarak bir uygulama example.sodoğru olarak tanımlayabiliyor mu? Kullanılması gereken numaralarla ilgili herhangi bir kural var mı? Yoksa bu basitçe kongre mi? Bu durumda, Windows'ta yazılım ikili dosyalarının sistemler arasında aktarıldığı durumlarda, bir sistem paylaşılan bir nesnenin daha yeni bir sürümüne sahipse, kaynaktan derlerken otomatik olarak eski sürüme bağlanır mı?

Bununla ilgili olduğundan şüpheleniyorum ldconfigama nasıl olduğundan emin değilim.

Yanıtlar:


87

İkili dosyalar, paylaşılan bir kütüphanenin hangi sürümüne bağlı olduklarını bilir ve özellikle talep eder. lddBağımlılıkları göstermek için kullanabilirsiniz ; benim için ls:

$ ldd /bin/ls
    linux-gate.so.1 =>  (0xb784e000)
    librt.so.1 => /lib/librt.so.1 (0xb782c000)
    libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
    libc.so.6 => /lib/libc.so.6 (0xb76dc000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
    /lib/ld-linux.so.2 (0xb784f000)
    libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)

Gördüğünüz gibi, sadece işaret libpthread.so.0etmiyor libpthread.so.


Sembolik bağlantının sebebi linker içindir. libpthread.soDoğrudan karşı bağlantı kurmak istediğinizde gcc, bayrak verin -lpthread, libönek ve .sosonek otomatik olarak ekler . Son .so.0eki eklemesini söyleyemezsiniz , bu yüzden sembolik bağlantı onu kolaylaştırmak için lib'in en yeni sürümüne işaret eder.


Eşittir işareti "= ls" olmamalıdır. Sadece "ldd ls" kullanın
bmacnaughton

1
@bmacnaughton Bu muhtemelen bir hata verecektir çünkü lddçalıştırılabilir dosyanın tam yolunu gerektirir. =lsBunu zsh'da yapar, ancak bunu değiştirdim çünkü herkes bu kabuğu kullanmıyor
Michael Mrozek

İlginç. Ubuntu'da bash kullanıyorum ve tam yoldan çalışmıyor gibi görünüyor. Açıklama için teşekkürler - Ben zsh kullanmıyorum.
bmacnaughton

60

Paylaşılan kütüphanelerdeki sayılar, bir kütüphane API'sini tanımlamak için Linux'ta kullanılan kurallardır. Genellikle, biçim:

libFOO.so.MAJOR.MINOR

Ve genellikle fark ettiğiniz gibi libFOO.so ile libFOO.so.MAJOR.MINOR arasında sembolik bir bağlantı vardır. Bu bağlantıyı en yeni sürüme güncellemekten ldconfig sorumludur.

MAJOR tipik olarak API değiştiğinde arttırılır (yeni giriş noktaları kaldırılır veya parametreler veya türler değiştirilir). MINOR tipik olarak hata düzeltme sürümleri için veya mevcut API'leri bozmadan yeni API'ler sunulduğunda artırılır.

Burada daha kapsamlı bir tartışma bulunabilir: Paylaşılan kütüphanelerin paylaşılması


Merhaba Miguel, bunun için teşekkür ederim, iki cevabı kabul edemem, çünkü yukarıdakileri güzel bir şekilde tamamlar. Benden +1, mükemmel bağlantı, tekrar teşekkürler!

4
Bu neredeyse doğru, ama aslında libFOO.so.MAJOR.MINOR(sonunda değil)
JonnyJD

6
Bu cevap çok yanlış . İlk olarak, gördüğünüz sayıların API ile hiçbir ilgisi yok, bunlar tamamen ABI. İkincisi, buradaki kongre, cevap verdiğiniz gibi AT ALL'ın anlamsal bir versiyonudur. Aksine o ld.so karşılaştırmak (görebilecekleri tek bir kitaplık sürüm numarasına eşleme güzel özelliği olan bir Libtool kongresi gnu.org/software/libtool/manual/html_node/... fazla bilgi için)
NewbiZ

23

Paylaşılan kütüphaneler aşağıdaki şemaya göre versiyonlanmalıdır:

blah.so.X.Y.Z

nerede

  • X = geriye dönük uyumsuz ABI sürümü
  • Y = geriye dönük uyumlu ABI sürümü
  • Z = Sadece dahili değişiklikler - ABI’de değişiklik yok

Tipik olarak sadece ilk haneyi görürsünüz, hello.so.1çünkü ilk rakam kütüphanenin "versiyonunu" tanımlamak için gereken tek şeydir, çünkü diğer tüm rakamlar geriye dönük olarak uyumludur.

ldconfigBir sistemde paylaşılan kütüphanelerin mevcut olduğu ve bu kütüphaneye giden yolun bulunduğu bir tablo tutar. Bunu çalıştırarak doğrulayabilirsiniz:

ldconfig -p

Red Hat gibi bir şey için bir paket yapıldığında, ikili dosyada çağrılan paylaşılan kütüphaneler aranacak ve RPM oluşturma zamanında paketin bağımlılıkları olarak eklenecektir. Bu nedenle, paketi yüklemeye gittiğinde hello.so.1, yükleyici sisteme yüklenip yüklenmediğini kontrol ederek arayacaktır ldconfig.

Bir paketin bağımlılıklarını şöyle bir şey yaparak görebilirsiniz:

rpm -qpR hello.rpm

Bu sistem (Windows'un aksine) hello.sobir sistemde birden fazla sürümünün kurulmasına ve aynı anda farklı uygulamalar tarafından kullanılmasına izin verir .


Bence bu en iyi cevap.
Kemin Zhou

1
Paylaşılan kütüphaneler aşağıdaki şemaya göre versiyonlanmalıdır (…) - Lütfen bu ifadeye referans verebilir misiniz?
Piotr Dobrogost

19

libNAME.so, derleyici / linker tarafından -lNAME tarafından belirtilen bir kütüphane ararken ilk kullanılan dosya adıdır. Paylaşılan bir kütüphane dosyasının içinde SONAME adlı bir alan bulunur. Bu alan, kütüphanenin kendisi önce derleme işlemi tarafından paylaşılan bir nesneye (yani) bağlandığında ayarlanır. Bu SONAME aslında, paylaşılan nesneye bağlı olduğu paylaşılan nesneye bağlı olarak bir bağlayıcının yürütülebilir bir dosyada depoladığı şeydir. Normal olarak SONAME, libNAME.so.MAJOR formundadır ve kitaplık kendisine bağlı mevcut çalıştırılabilirlerle uyumsuz hale geldiğinde her zaman değiştirilir ve kütüphanenin her iki büyük sürümü de gerektiğinde kurulabilir (ancak bir tanesi geliştirme için gösterilecektir) libNAME.so) Ayrıca, bir kütüphanenin küçük sürümleri arasında kolayca yükseltmeyi desteklemek için, libNAME.so.MAJOR normalde libNAME.so.MAJOR.MINOR gibi bir dosyanın bağlantısıdır. Yeni bir küçük sürüm kurulabilir ve bir kez tamamlandıktan sonra, eski küçük sürüme giden bağlantı, yükseltilmiş kitaplığı kullanmak için tüm yeni yürütmeleri hemen güncelleyerek yeni küçük sürüme işaret eder. Ayrıca cevabımı görünLinux, GNU GCC, ld, sürüm komut dosyaları ve ELF ikili formatı - Nasıl çalışır?

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.