web-dev-qa-db-ger.com

Unterschied zwischen gemeinsam genutzten Objekten (.so), statischen Bibliotheken (.a) und DLLs (.so)?

Ich war an einigen Debatten in Bezug auf Bibliotheken in Linux beteiligt und möchte einige Dinge bestätigen.

Soweit ich weiß (bitte korrigieren Sie mich, wenn ich mich irre und ich meinen Beitrag später bearbeite), gibt es zwei Möglichkeiten, Bibliotheken beim Erstellen einer Anwendung zu verwenden:

  1. Statische Bibliotheken (.a-Dateien): Zum Zeitpunkt der Verknüpfung wird eine Kopie der gesamten Bibliothek in die endgültige Anwendung eingefügt, sodass die Funktionen in der Bibliothek für die aufrufende Anwendung immer verfügbar sind
  2. Freigegebene Objekte (.so-Dateien): Zum Zeitpunkt der Verknüpfung wird das Objekt nur anhand seiner API über die entsprechende Headerdatei (.h) überprüft. Die Bibliothek wird erst zur Laufzeit verwendet, wenn sie benötigt wird.

Der offensichtliche Vorteil statischer Bibliotheken besteht darin, dass die gesamte Anwendung in sich geschlossen werden kann, während der Vorteil dynamischer Bibliotheken darin besteht, dass die ".so" -Datei ersetzt werden kann (dh, falls sie aus Sicherheitsgründen aktualisiert werden muss) Fehler), ohne dass die Basisanwendung neu kompiliert werden muss.

Ich habe gehört, dass einige Leute zwischen gemeinsam genutzten Objekten und dynamisch verknüpften Bibliotheken (DLLs) unterscheiden, obwohl sie beide ".so" -Dateien sind. Gibt es einen Unterschied zwischen gemeinsam genutzten Objekten und DLLs bei der C/C++ - Entwicklung unter Linux oder einem anderen POSIX-kompatiblen Betriebssystem (z. B. MINIX, UNIX, QNX usw.)? Mir wurde gesagt, dass ein wesentlicher Unterschied (bisher) darin besteht, dass gemeinsam genutzte Objekte nur zur Laufzeit verwendet werden, während DLLs zuerst mit dem Aufruf dlopen () in der Anwendung geöffnet werden müssen.

Schließlich habe ich auch von einigen Entwicklern gehört, dass sie "freigegebene Archive" erwähnen, die nach meinem Verständnis auch selbst statische Bibliotheken sind, aber von einer Anwendung niemals direkt verwendet werden. Stattdessen werden andere statische Bibliotheken mit den "freigegebenen Archiven" verknüpft, um einige (aber nicht alle) Funktionen/Ressourcen aus dem freigegebenen Archiv in die zu erstellende statische Bibliothek zu ziehen.

Vielen Dank im Voraus für Ihre Hilfe.

Aktualisieren


In dem Kontext, in dem mir diese Begriffe zur Verfügung gestellt wurden, handelte es sich tatsächlich um fehlerhafte Begriffe, die von einem Team von Windows-Entwicklern verwendet wurden, die Linux lernen mussten. Ich habe versucht, sie zu korrigieren, aber die (falschen) Sprachnormen blieben bestehen.

  1. Shared Object: Eine Bibliothek, die beim Programmstart automatisch mit einem Programm verknüpft wird und als eigenständige Datei vorhanden ist. Die Bibliothek wird beim Kompilieren in die Verknüpfungsliste aufgenommen (dh: LDOPTS+=-lmylib Für eine Bibliotheksdatei mit dem Namen mylib.so). Die Bibliothek muss zum Zeitpunkt der Kompilierung und beim Start der Anwendung vorhanden sein.
  2. Statische Bibliothek: Eine Bibliothek, die zum Erstellungszeitpunkt für eine einzelne (größere) Anwendung mit dem eigentlichen Programm selbst zusammengeführt wird. Sie enthält den Anwendungscode und den Bibliothekscode, der beim Erstellen des Programms automatisch mit einem Programm verknüpft wird, und die endgültige Binärdatei, die beides enthält Das Hauptprogramm und die Bibliothek selbst sind als eigenständige Binärdatei vorhanden. Die Bibliothek wird beim Kompilieren in die Verknüpfungsliste aufgenommen (dh: LDOPTS+=-lmylib Für eine Bibliotheksdatei mit dem Namen mylib.a). Die Bibliothek muss zur Kompilierungszeit vorhanden sein.
  3. DLL: Im Wesentlichen dasselbe wie ein gemeinsam genutztes Objekt, aber anstatt zur Kompilierungszeit in die Verknüpfungsliste aufgenommen zu werden, wird die Bibliothek über dlopen()/dlsym()-Befehle geladen, sodass die Bibliothek dies nicht tut müssen zum Zeitpunkt der Erstellung vorhanden sein, damit das Programm kompiliert werden kann. Außerdem muss die Bibliothek nicht (unbedingt) beim Start der Anwendung oder beim Kompilieren vorhanden sein, da sie nur zum Zeitpunkt des Aufrufs von dlopen/dlsym benötigt wird werden hergestellt.
  4. Shared Archive: Entspricht im Wesentlichen einer statischen Bibliothek, wird jedoch mit den Flags "export-shared" und "-fPIC" kompiliert. Die Bibliothek wird zur Kompilierungszeit in die Verknüpfungsliste aufgenommen (dh: LDOPTS + = - lmylib S für eine Bibliotheksdatei mit dem Namen mylib S. A). Der Unterschied zwischen beiden besteht darin, dass dieses zusätzliche Flag erforderlich ist, wenn ein freigegebenes Objekt oder DLL das freigegebene Archiv statisch in einen eigenen Code verknüpfen UND die Funktionen im freigegebenen Objekt verfügbar machen soll Dies ist hilfreich, wenn jemand Ihnen eine statische Bibliothek zur Verfügung stellt und Sie diese als SO neu packen möchten. Die Bibliothek muss beim Kompilieren vorhanden sein Zeit.

Zusätzliches Update

Die Unterscheidung zwischen "DLL" und "shared library" War nur eine (faule, ungenaue) Umgangssprache in der Firma, in der ich zu der Zeit gearbeitet habe (Windows-Entwickler waren gezwungen, auf Linux-Entwicklung umzusteigen, und der Begriff steckt), unter Beachtung der oben genannten Beschreibungen.

Darüber hinaus war das nach dem Bibliotheksnamen folgende "S" - Literal im Fall von "gemeinsam genutzten Archiven" nur eine Konvention, die in diesem Unternehmen und nicht in der Branche im Allgemeinen verwendet wurde.

247
DevNull

Ich habe immer gedacht, dass DLLs und gemeinsam genutzte Objekte nur unterschiedliche Begriffe für dasselbe sind - Windows nennt sie DLLs, während sie auf UNIX-Systemen gemeinsam genutzte Objekte sind open a .so unter UNIX heißt dlopen() nach 'dynamic library').

Sie werden zwar nur beim Start der Anwendung verknüpft, Ihre Vorstellung von der Überprüfung der Header-Datei ist jedoch falsch. Die Header-Datei definiert Prototypen, die erforderlich sind, um den Code zu kompilieren, der die Bibliothek verwendet. Zum Zeitpunkt der Verknüpfung überprüft der Linker jedoch die Bibliothek selbst, um sicherzustellen, dass die benötigten Funktionen tatsächlich vorhanden sind. Der Linker muss die Funktionskörper irgendwo zum Zeitpunkt des Links finden, sonst wird ein Fehler ausgelöst. Dies geschieht AUCH zur Laufzeit, da sich, wie Sie zu Recht bemerken, die Bibliothek selbst möglicherweise geändert hat, seit das Programm kompiliert wurde. Aus diesem Grund ist die ABI-Stabilität in Plattformbibliotheken so wichtig, da die ABI-Änderung bestehende Programme bricht, die mit älteren Versionen kompiliert wurden.

Statische Bibliotheken sind nur Bündel von Objektdateien, die direkt aus dem Compiler stammen, genau wie die, die Sie selbst als Teil der Kompilierung Ihres Projekts erstellen. Sie werden also genauso in den Linker gezogen und dort eingespeist, und nicht verwendete Bits sind es genau auf die gleiche Weise fallen gelassen.

86
Matthew Walton

Eine statische Bibliothek (.a) ist eine Bibliothek, die direkt mit der vom Linker erstellten endgültigen ausführbaren Datei verknüpft werden kann, in der sie enthalten ist und die nicht im System vorhanden sein muss, in dem sich die ausführbare Datei wird bereitgestellt.

Eine gemeinsam genutzte Bibliothek (.so) ist eine Bibliothek, die verknüpft, aber nicht in die endgültige ausführbare Datei eingebettet ist. Sie wird beim Start der ausführbaren Datei geladen und muss auf dem System vorhanden sein, auf dem die ausführbare Datei bereitgestellt wird .

Eine Dynamic Link Library unter Windows (.dll) ist wie eine Shared Library (.so) unter Linux, es gibt jedoch einige Unterschiede zwischen den beiden Implementierungen, die sich auf das Betriebssystem beziehen (Windows vs. Linux):

Eine DLL kann zwei Arten von Funktionen definieren: exportierte und interne. Die exportierten Funktionen sollen von anderen Modulen aufgerufen werden, sowie von innerhalb der DLL, wo sie definiert sind. Interne Funktionen sollen normalerweise nur von innerhalb der DLL wo sie definiert sind.

Eine ALSO - Bibliothek unter Linux benötigt keine spezielle Exportanweisung, um exportierbare Symbole anzuzeigen, da alle Symbole für einen Abfrageprozess verfügbar sind.

177
aleroot

Ich kann auf die Details von DLLs in Windows eingehen, um meinen Freunden hier in * NIX-Land diese Geheimnisse näher zu bringen ...

Ein DLL ist wie eine Shared Object-Datei. Beides sind Images, die vom Programmlader des jeweiligen Betriebssystems in den Speicher geladen werden können. Die Bilder werden von verschiedenen Metadatenbits begleitet, damit Linker und Loader die erforderlichen Verknüpfungen herstellen und die Codebibliothek verwenden können.

Windows-DLLs haben eine Exporttabelle. Die Exporte können nach Name oder Tabellenposition (numerisch) erfolgen. Die letztere Methode wird als "alte Schule" betrachtet und ist viel fragiler - das Wiederherstellen der DLL und das Ändern der Position einer Funktion in der Tabelle führt zu einer Katastrophe, wohingegen beim Verknüpfen von Einträgen keine wirklichen Probleme auftreten Punkte ist nach Namen. Vergessen Sie dies als Problem, aber beachten Sie, dass es vorhanden ist, wenn Sie mit "Dinosaurier" -Code arbeiten, z. B. Bibliotheken von Drittanbietern.

Windows-DLLs werden durch Kompilieren und Verknüpfen erstellt, genau wie bei einer EXE-Datei (ausführbare Anwendung), aber die DLL ist nicht als eigenständige Datei gedacht, genau wie eine SO von einer Anwendung verwendet werden, entweder durch dynamisches Laden oder durch Link-Time-Bindung (der Verweis auf SO ist in die Metadaten der Anwendungsbinärdatei eingebettet, und der OS-Programmlader lädt die SOs, auf die verwiesen wird, automatisch) . DLLs können auf andere DLLs verweisen, genauso wie SOs auf andere SOs verweisen können.

In Windows stellen DLLs nur bestimmte Einstiegspunkte zur Verfügung. Diese werden "Exporte" genannt. Der Entwickler kann entweder ein spezielles Compiler-Schlüsselwort verwenden, um ein Symbol von außen sichtbar zu machen (für andere Linker und den Dynamic Loader), oder die Exporte können in einer Moduldefinitionsdatei aufgelistet werden, die zum Zeitpunkt der Verknüpfung verwendet wird, wenn DLL selbst wird erstellt. Die moderne Praxis besteht darin, die Funktionsdefinition mit dem Schlüsselwort zu dekorieren, um den Symbolnamen zu exportieren. Es ist auch möglich, Header-Dateien mit Schlüsselwörtern zu erstellen, die dieses Symbol als eines deklarieren, das aus einem DLL außerhalb der aktuellen Kompilierungseinheit importiert werden soll. Weitere Informationen finden Sie in den Schlüsselwörtern __declspec (dllexport) und __declspec (dllimport).

Eine der interessanten Eigenschaften von DLLs ist, dass sie eine Standardhandlerfunktion "beim Laden/Entladen" deklarieren können. Immer wenn die DLL geladen oder entladen wird, kann die DLL eine Initialisierung oder Bereinigung durchführen. Dies passt gut zu einem DLL als objektorientiertem Ressourcenmanager, z. B. einem Gerätetreiber oder einer Schnittstelle für gemeinsam genutzte Objekte.

Wenn ein Entwickler eine bereits erstellte DLL verwenden möchte, muss er entweder auf eine "Exportbibliothek" (* .LIB) verweisen, die vom Entwickler DLL beim Erstellen der DLL erstellt wurde, oder er muss das _ explizit laden.DLL zur Laufzeit und fordern Sie die Einstiegspunktadresse über die Mechanismen LoadLibrary () und GetProcAddress () namentlich an. Das Verknüpfen mit einer LIB-Datei (die einfach die Linker-Metadaten für die exportierten Einstiegspunkte der DLL enthält) ist in den meisten Fällen die Methode, mit der DLLs verwendet werden. Das dynamische Laden ist in der Regel für die Implementierung von "Polymorphismus" oder "Laufzeitkonfigurierbarkeit" in Programmverhalten (Zugriff auf Add-Ons oder später definierte Funktionen, auch "Plug-Ins" genannt) reserviert.

Die Windows-Vorgehensweise kann manchmal Verwirrung stiften. Das System verwendet die Erweiterung .LIB, um sowohl auf normale statische Bibliotheken (Archive wie POSIX * .a-Dateien) als auch auf die "Export-Stub" -Bibliotheken zu verweisen, die zum Binden einer Anwendung an eine DLL zum Zeitpunkt der Verknüpfung erforderlich sind. Man sollte also immer nachsehen, ob eine * .LIB-Datei den gleichen Namen hat wie eine * .DLL-Datei. Andernfalls ist die Wahrscheinlichkeit groß, dass es sich bei der * .LIB-Datei um ein statisches Bibliotheksarchiv handelt und keine Bindungsmetadaten für eine DLL exportiert werden.

29
JoGusto

Sie haben Recht, dass statische Dateien zur Link-Zeit in die Anwendung kopiert werden und freigegebene Dateien nur zur Link-Zeit überprüft und zur Laufzeit geladen werden.

Der Aufruf von dlopen gilt nicht nur für freigegebene Objekte, wenn die Anwendung dies zur Laufzeit in ihrem Namen wünscht. Andernfalls werden die freigegebenen Objekte beim Start der Anwendung automatisch geladen. DLLS und .so sind dasselbe. das dlopen ist vorhanden, um noch feinere dynamische Ladefähigkeiten für Prozesse hinzuzufügen. Sie müssen dlopen nicht selbst verwenden, um die DLLs zu öffnen/zu verwenden. Dies geschieht auch beim Start der Anwendung.

4
rapadura