GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Umgang mit dynamischen und statischen Bibliotheken unter Linux

Linux ist gewissermaßen eine Reihe statischer und dynamischer Bibliotheken, die voneinander abhängen. Für neue Benutzer von Linux-basierten Systemen kann der gesamte Umgang mit Bibliotheken ein Rätsel sein. Aber mit etwas Erfahrung kann die enorme Menge an gemeinsam genutztem Code, der in das Betriebssystem integriert ist, beim Schreiben neuer Anwendungen von Vorteil sein.

Um Ihnen den Einstieg in dieses Thema zu erleichtern, habe ich ein kleines Anwendungsbeispiel vorbereitet, das die gängigsten Methoden zeigt, die auf gängigen Linux-Distributionen funktionieren (diese wurden nicht auf anderen Systemen getestet). Um diesem praktischen Lernprogramm mit der Beispielanwendung zu folgen, öffnen Sie eine Eingabeaufforderung und geben Sie Folgendes ein:

$ git clone https://github.com/hANSIc99/library_sample
$ cd library_sample/
$ make
cc -c main.c -Wall -Werror
cc -c libmy_static_a.c -o libmy_static_a.o -Wall -Werror
cc -c libmy_static_b.c -o libmy_static_b.o -Wall -Werror
ar -rsv libmy_static.a libmy_static_a.o libmy_static_b.o
ar:Erstellen von libmy_static.a
a - libmy_static_a.o
a - libmy_static_b.o
cc -c -fPIC libmy_shared.c -o libmy_shared.o
cc - shared -o libmy_shared.so libmy_shared.o
$ make clean
rm *.o

Nach dem Ausführen dieser Befehle sollten diese Dateien dem Verzeichnis hinzugefügt werden (führen Sie ls aus um sie zu sehen):

my_app
libmy_static.a
libmy_shared.so

Über statisches Linken

Wenn Ihre Anwendung mit einer statischen Bibliothek verknüpft wird, wird der Code der Bibliothek Teil der resultierenden ausführbaren Datei. Dies wird nur einmal zum Zeitpunkt des Linkens durchgeführt, und diese statischen Bibliotheken enden normalerweise mit einem .a Erweiterung.

Eine statische Bibliothek ist ein Archiv (ar) von Objektdateien. Die Objektdateien sind normalerweise im ELF-Format. ELF ist die Abkürzung für Executable and Linkable Format, das mit vielen Betriebssystemen kompatibel ist.

Die Ausgabe der file Befehl sagt Ihnen, dass die statische Bibliothek libmy_static.a ist das ar Archivtyp:

$-Datei libmy_static.a
libmy_static.a:aktuelles ar-Archiv

Mit ar -t , können Sie in dieses Archiv schauen; es zeigt zwei Objektdateien:

$ ar -t libmy_static.a 
libmy_static_a.o
libmy_static_b.o

Sie können die Dateien des Archivs mit ar -x <archive-file> extrahieren . Die extrahierten Dateien sind Objektdateien im ELF-Format:

$ ar -x libmy_static.a
$ file libmy_static_a.o
libmy_static_a.o:ELF 64-bit LSB verschiebbar, x86-64, Version 1 (SYSV), nicht entfernt

Über dynamisches Linken

Weitere Linux-Ressourcen

  • Spickzettel für Linux-Befehle
  • Spickzettel für fortgeschrittene Linux-Befehle
  • Kostenloser Online-Kurs:RHEL Technical Overview
  • Spickzettel für Linux-Netzwerke
  • SELinux-Spickzettel
  • Spickzettel für allgemeine Linux-Befehle
  • Was sind Linux-Container?
  • Unsere neuesten Linux-Artikel

Dynamisches Linken bedeutet die Verwendung gemeinsam genutzter Bibliotheken. Geteilte Bibliotheken enden normalerweise mit .so (kurz für „gemeinsames Objekt“).

Shared Libraries sind die gebräuchlichste Art, Abhängigkeiten auf Linux-Systemen zu verwalten. Diese gemeinsam genutzten Ressourcen werden vor dem Start der Anwendung in den Arbeitsspeicher geladen, und wenn mehrere Prozesse dieselbe Bibliothek benötigen, wird sie nur einmal auf dem System geladen. Diese Funktion spart Speicherplatz durch die Anwendung.

Beachten Sie auch, dass jede Anwendung, die auf diese Bibliothek verweist, davon profitiert, wenn ein Fehler in einer gemeinsam genutzten Bibliothek behoben wird. Das bedeutet auch, dass, wenn der Fehler unentdeckt bleibt, jede verweisende Anwendung darunter leidet (wenn die Anwendung die betroffenen Teile verwendet).

Für Anfänger kann es sehr schwierig sein, wenn eine Anwendung eine bestimmte Version der Bibliothek erfordert, der Linker jedoch nur den Speicherort einer inkompatiblen Version kennt. In diesem Fall müssen Sie dem Linker helfen, den Pfad zur richtigen Version zu finden.

Obwohl dies kein alltägliches Problem ist, hilft Ihnen das Verständnis der dynamischen Verknüpfung sicherlich bei der Behebung solcher Probleme.

Glücklicherweise ist die Mechanik dafür recht einfach.

Um zu erkennen, welche Bibliotheken zum Starten einer Anwendung erforderlich sind, können Sie ldd verwenden , die die gemeinsam genutzten Bibliotheken ausgibt, die von einer bestimmten Datei verwendet werden:

$ ldd my_app 
        linux-vdso.so.1 (0x00007ffd1299c000)
        libmy_shared.so => ​​nicht gefunden
        libc.so.6 => /lib64/libc.so.6 (0x00007f56b869b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f56b8881000)

Beachten Sie, dass die Bibliothek libmy_shared.so ist Teil des Repositorys, wird aber nicht gefunden. Dies liegt daran, dass der dynamische Linker, der dafür verantwortlich ist, alle Abhängigkeiten in den Speicher zu laden, bevor er die Anwendung ausführt, diese Bibliothek nicht an den Standardspeicherorten finden kann, die er durchsucht.

Fehler im Zusammenhang mit Linkern, die inkompatible Versionen gängiger Bibliotheken finden (wie bzip2 , zum Beispiel) kann für einen neuen Benutzer ziemlich verwirrend sein. Eine Möglichkeit, dies zu umgehen, besteht darin, den Repository-Ordner zur Umgebungsvariable LD_LIBRARY_PATH hinzuzufügen um dem Linker mitzuteilen, wo er nach der richtigen Version suchen soll. In diesem Fall befindet sich die richtige Version in diesem Ordner, sodass Sie sie exportieren können:

$ LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
$ LD_LIBRARY_PATH exportieren

Jetzt weiß der dynamische Linker, wo er die Bibliothek findet, und die Anwendung kann ausgeführt werden. Sie können ldd erneut ausführen zum Aufrufen des dynamischen Linkers, der die Abhängigkeiten der Anwendung überprüft und in den Arbeitsspeicher lädt. Die Speicheradresse wird nach dem Objektpfad angezeigt:

$ ldd my_app 
        linux-vdso.so.1 (0x00007ffd385f7000)
        libmy_shared.so => ​​/home/stephan/library_sample/libmy_shared.so (0x00007f3fad401000)
        libc.so. 6 => /lib64/libc.so.6 (0x00007f3fad21d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3fad408000)

Um herauszufinden, welcher Linker aufgerufen wird, können Sie file verwenden :

$ file my_app 
my_app:ELF 64-bit LSB ausführbar, x86-64, Version 1 (SYSV), dynamisch verlinkt, Interpreter /lib64/ld-linux-x86-64.so.2, BuildID[ sha1]=26c677b771122b4c99f0fd9ee001e6c743550fa6, für GNU/Linux 3.2.0, nicht entfernt

Der Linker /lib64/ld-linux-x86–64.so.2 ist ein symbolischer Link zu ld-2.30.so , das ist der Standard-Linker für meine Linux-Distribution:

$-Datei /lib64/ld-linux-x86-64.so.2 
/lib64/ld-linux-x86-64.so.2:symbolischer Link zu ld-2.31.so

Rückblick auf die Ausgabe von ldd , können Sie auch sehen (neben libmy_shared.so ), dass jede Abhängigkeit mit einer Zahl endet (z. B. /lib64/libc.so.6 ). Das übliche Namensschema gemeinsam genutzter Objekte ist:

**lib** XYZ.so **.<MAJOR>** . **<MINOR>** 

Auf meinem System libc.so.6 ist auch ein symbolischer Link auf das gemeinsame Objekt libc-2.30.so im selben Ordner:

$-Datei /lib64/libc.so.6 
/lib64/libc.so.6:symbolischer Link zu libc-2.31.so

Wenn Sie mit dem Problem konfrontiert sind, dass eine Anwendung nicht gestartet wird, weil die geladene Bibliothek die falsche Version hat, können Sie dieses Problem sehr wahrscheinlich beheben, indem Sie die symbolischen Links überprüfen und neu anordnen oder den richtigen Suchpfad angeben (siehe "Der dynamische Ladeprogramm :ld.so" unten).

Weitere Informationen finden Sie im ldd Manpage.

Dynamisches Laden

Dynamisches Laden bedeutet, dass eine Bibliothek (z. B. ein .so Datei) wird während der Laufzeit eines Programms geladen. Dies geschieht über ein bestimmtes Programmierschema.

Dynamisches Laden wird angewendet, wenn eine Anwendung Plugins verwendet, die während der Laufzeit geändert werden können.

Siehe dlopen Manpage für weitere Informationen.

Der dynamische Loader:ld.so

Unter Linux haben Sie es hauptsächlich mit gemeinsam genutzten Objekten zu tun, daher muss es einen Mechanismus geben, der die Abhängigkeiten einer Anwendung erkennt und sie in den Speicher lädt.

ld.so sucht an diesen Orten in der folgenden Reihenfolge nach gemeinsam genutzten Objekten:

  1. Der relative oder absolute Pfad in der Anwendung (fest codiert mit dem -rpath Compiler-Option auf GCC)
  2. In der Umgebungsvariable LD_LIBRARY_PATH
  3. In der Datei /etc/ld.so.cache

Denken Sie daran, eine Bibliothek zum Systembibliotheksarchiv /usr/lib64 hinzuzufügen erfordert Administratorrechte. Sie könnten libmy_shared.so kopieren manuell in das Bibliotheksarchiv und sorgen dafür, dass die Anwendung funktioniert, ohne LD_LIBRARY_PATH festzulegen :

LD_LIBRARY_PATH aufheben
sudo cp libmy_shared.so /usr/lib64/

Wenn Sie ldd ausführen , können Sie sehen, dass der Pfad zum Bibliotheksarchiv jetzt angezeigt wird:

$ ldd my_app 
        linux-vdso.so.1 (0x00007ffe82fab000)
        libmy_shared.so => ​​/lib64/libmy_shared.so (0x00007f0a963e0000)
        libc.so.6 => / lib64/libc.so.6 (0x00007f0a96216000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0a96401000)

Passen Sie die gemeinsam genutzte Bibliothek zur Kompilierzeit an

Wenn Sie möchten, dass Ihre Anwendung Ihre gemeinsam genutzten Bibliotheken verwendet, können Sie während der Kompilierzeit einen absoluten oder relativen Pfad angeben.

Modifizieren Sie das Makefile (Zeile 10) und kompilieren Sie das Programm neu, indem Sie make -B aufrufen . Dann die Ausgabe von ldd zeigt libmy_shared.so wird mit seinem absoluten Pfad aufgelistet.

Ändern Sie dies:

CFLAGS =-Wall -Werror -Wl,-rpath,$(shell pwd)  

Dazu (Achten Sie darauf, den Benutzernamen zu bearbeiten):

CFLAGS =/home/stephan/library_sample/libmy_shared.so  

Dann neu kompilieren:

$ make 

Bestätigen Sie, dass der von Ihnen festgelegte absolute Pfad verwendet wird, den Sie in Zeile 2 der Ausgabe sehen können:

$ ldd my_app
    linux-vdso.so.1 (0x00007ffe143ed000)
        libmy_shared.so => ​​/lib64/libmy_shared.so (0x00007fe50926d000)
        /home/stephan/library_sample/libmy_shared .so (0x00007fe509268000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fe50909e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe50928e000)

Dies ist ein gutes Beispiel, aber wie würde das funktionieren, wenn Sie eine Bibliothek erstellen würden, die andere verwenden können? Neue Bibliotheksstandorte können registriert werden, indem sie in /etc/ld.so.conf geschrieben werden oder Erstellen einer <library-name>.conf Datei mit dem Speicherort unter /etc/ld.so.conf.d/ . Danach ldconfig muss ausgeführt werden, um den ld.so.cache neu zu schreiben Datei. Dieser Schritt ist manchmal notwendig, nachdem Sie ein Programm installiert haben, das einige spezielle gemeinsam genutzte Bibliotheken mitbringt.

Siehe ld.so Manpage für weitere Informationen.

Wie man mit mehreren Architekturen umgeht

Normalerweise gibt es unterschiedliche Bibliotheken für die 32-Bit- und 64-Bit-Versionen von Anwendungen. Die folgende Liste zeigt ihre Standardspeicherorte für verschiedene Linux-Distributionen:

Red Hat-Familie

  • 32-Bit:/usr/lib
  • 64-Bit:/usr/lib64

Debian-Familie

  • 32-Bit:/usr/lib/i386-linux-gnu
  • 64-Bit:/usr/lib/x86_64-linux-gnu

Arch Linux-Familie

  • 32-Bit:/usr/lib32
  • 64-Bit:/usr/lib64

FreeBSD (technisch keine Linux-Distribution)

  • 32bit:/usr/lib32
  • 64bit:/usr/lib

Wenn Sie wissen, wo Sie nach diesen Schlüsselbibliotheken suchen müssen, gehören fehlerhafte Bibliotheksverknüpfungen der Vergangenheit an.

Auch wenn es zunächst verwirrend sein mag, ist das Verständnis der Abhängigkeitsverwaltung in Linux-Bibliotheken eine Möglichkeit, das Gefühl zu haben, die Kontrolle über das Betriebssystem zu haben. Führen Sie diese Schritte mit anderen Anwendungen durch, um sich mit gängigen Bibliotheken vertraut zu machen, und lernen Sie weiter, wie Sie Probleme mit Bibliotheken beheben können, die auf Ihrem Weg auftreten könnten.


Linux
  1. So verwalten und listen Sie Dienste in Linux auf

  2. So installieren und testen Sie Ansible unter Linux

  3. So legen Sie eine statische IP-Adresse fest und ändern die Routing-Tabelle unter Linux

  4. So installieren und verwenden Sie Flatpak unter Linux

  5. So konfigurieren Sie statische und dynamische IP-Adressen in Arch Linux

So benennen Sie Dateien und Verzeichnisse in Linux um

So komprimieren Sie Dateien und Verzeichnisse unter Linux

So installieren und verwenden Sie PuTTY unter Linux

So konfigurieren Sie eine statische IP-Adresse in Linux und Unix

So installieren und verwenden Sie phpMyAdmin unter Linux

So konfigurieren Sie eine statische IP-Adresse unter Alpine Linux