Jak działają liczby SO (obiekt współdzielony)?


123

Wiem, że współdzielone obiekty pod Linuksem używają „więc liczb”, a mianowicie, że różne wersje współdzielonego obiektu mają różne rozszerzenia, na przykład:

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

Rozumiem, że chodzi o to, aby mieć dwa różne pliki, tak aby dwie wersje biblioteki mogły istnieć w systemie (w przeciwieństwie do „DLL Hell” w systemie Windows). Chciałbym wiedzieć, jak to działa w praktyce? Często widzę, że example.sojest w rzeczywistości dowiązaniem do example.so.2gdzie .2jest najnowsza wersja. Jak zatem aplikacja w zależności od starszej wersji example.sopoprawnie ją identyfikuje? Czy istnieją jakieś zasady dotyczące tego, jakich liczb należy używać? Czy jest to po prostu konwencja? Czy w przeciwieństwie do systemu Windows, w którym binarne oprogramowanie jest przesyłane między systemami, jeśli system ma nowszą wersję obiektu współużytkowanego, jest on automatycznie łączony ze starszą wersją podczas kompilacji ze źródła?

Podejrzewam, że jest to związane, ldconfigale nie jestem pewien jak.

Odpowiedzi:


87

Same pliki binarne wiedzą, od której wersji biblioteki współdzielonej są zależne, i żądają jej konkretnie. Możesz użyć, lddaby pokazać zależności; moje lssą:

$ 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)

Jak widać, wskazuje to np. libpthread.so.0Nie tylko libpthread.so.


Powodem symbolicznego linku jest linker. Kiedy chcesz połączyć libpthread.sobezpośrednio, podajesz gccflagę -lpthread, która automatycznie dodaje libprefiks i .sosufiks. Nie możesz nakazać, aby .so.0dodała sufiks, więc symboliczny link wskazuje najnowszą wersję biblioteki lib, aby ułatwić


Znak równości „= ls” nie powinien być obecny. Wystarczy użyć „ldd ls”
bmacnaughton,

1
@bmacnaughton To prawdopodobnie spowoduje błąd, ponieważ lddwymaga pełnej ścieżki do pliku wykonywalnego. =lsrobi to w Zsh, ale zmieniłem to, ponieważ nie wszyscy używają tej powłoki
Michael Mrozek

Ciekawy. Uruchamiam bash na Ubuntu i wydaje się, że działa bez pełnej ścieżki. Dzięki za wyjaśnienie - nie używam zsh.
bmacnaughton

60

Liczby we współdzielonych bibliotekach są w Linuksie konwencją używaną do identyfikacji API biblioteki. Zazwyczaj format to:

libFOO.so.MAJOR.MINOR

I jak zauważyłeś, zwykle istnieje symboliczny link z libFOO.so do libFOO.so.MAJOR.MINOR. ldconfig jest odpowiedzialny za aktualizację tego linku do najnowszej wersji.

KIERUNEK jest zwykle zwiększany, gdy zmienia się interfejs API (nowe punkty wejścia są usuwane lub zmieniane są parametry lub typy). Wartość MINOR jest zwykle zwiększana w przypadku wydań poprawek błędów lub gdy nowe interfejsy API są wprowadzane bez uszkodzenia istniejących interfejsów API.

Bardziej szczegółową dyskusję można znaleźć tutaj: Analiza wspólnych bibliotek


Cześć Miguel, dzięki za to, szkoda, że ​​nie mogę zaakceptować dwóch odpowiedzi, ponieważ ładnie to uzupełnia. +1 ode mnie, też doskonały link, jeszcze raz dziękuję!

4
To prawie poprawne, ale tak naprawdę jest libFOO.so.MAJOR.MINOR(tak nie na końcu)
JonnyJD

6
Ta odpowiedź jest bardzo błędna . Po pierwsze, liczby, które widzisz, nie mają nic wspólnego z API, są to wyłącznie ABI. Po drugie, konwencja tutaj nie jest wersją semantyczną WSZYSTKO, jak sugerujesz odpowiedź. Jest to raczej konwencja libtool, która ma przyjemną właściwość mapowania na jeden numer wersji biblioteki, który ld.so może porównać ( więcej informacji na stronie gnu.org/software/libtool/manual/html_node/ ...)
NewbiZ

23

Biblioteki współdzielone powinny być wersjonowane zgodnie z następującym schematem:

blah.so.X.Y.Z

gdzie

  • X = wstecznie niekompatybilna wersja ABI
  • Y = wersja ABI kompatybilna wstecz
  • Z = Tylko zmiany wewnętrzne - bez zmiany ABI

Zazwyczaj widzisz tylko pierwszą cyfrę, hello.so.1ponieważ pierwsza cyfra jest jedyną rzeczą potrzebną do zidentyfikowania „wersji” biblioteki, ponieważ wszystkie pozostałe cyfry są kompatybilne wstecz.

ldconfigutrzymuje tabelę bibliotek współdzielonych dostępnych w systemie i miejsca, w którym istnieje ścieżka do tej biblioteki. Możesz to sprawdzić, uruchamiając:

ldconfig -p

Kiedy pakiet jest budowany dla czegoś takiego jak Red Hat, biblioteki współdzielone wywoływane w pliku binarnym zostaną wyszukane i dodane jako zależności pakietu w czasie kompilacji RPM. Dlatego po przejściu do instalacji pakietu instalator sprawdzi, czy hello.so.1system jest zainstalowany, czy nie ldconfig.

Możesz zobaczyć zależności pakietu, wykonując coś takiego:

rpm -qpR hello.rpm

Ten system (w przeciwieństwie do systemu Windows) pozwala na hello.sozainstalowanie wielu wersji tego systemu i korzystanie z niego przez różne aplikacje jednocześnie.


Myślę, że to najlepsza odpowiedź.
Kemin Zhou,

1
Biblioteki współdzielone powinny być wersjonowane zgodnie z następującym schematem (…) - Czy możesz podać odniesienie do tego oświadczenia?
Piotr Dobrogost

19

libNAME.so to nazwa pliku używana przez kompilator / linker przy pierwszym poszukiwaniu biblioteki określonej przez -lNAME. Wewnątrz pliku biblioteki współdzielonej znajduje się pole o nazwie SONAME. To pole jest ustawiane, gdy sama biblioteka jest najpierw łączona z obiektem współdzielonym (a więc) przez proces kompilacji. Ten SONAME jest tak naprawdę tym, co linker przechowuje w pliku wykonywalnym, w zależności od tego, jaki obiekt współdzielony jest z nim połączony. Zwykle SONAME ma postać libNAME.so.MAJOR i jest zmieniany za każdym razem, gdy biblioteka staje się niezgodna z istniejącymi połączonymi z nią plikami wykonywalnymi, a obie główne wersje biblioteki mogą być instalowane w razie potrzeby (choć tylko jedna będzie wskazywana do programowania jako libNAME.so) Ponadto, aby ułatwić łatwą aktualizację między mniejszymi wersjami biblioteki, libNAME.so.MAJOR jest zwykle linkiem do pliku takiego jak libNAME.so.MAJOR.MINOR. Można zainstalować nową wersję podrzędną, a po jej ukończeniu odsyłacz do starej wersji podrzędnej zostanie podbity, aby wskazać nową wersję podrzędną, która natychmiast aktualizuje wszystkie nowe wykonania w celu korzystania z zaktualizowanej biblioteki. Zobacz także moją odpowiedź naLinux, GNU GCC, ld, skrypty wersji i format binarny ELF - jak to działa?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.