In strace
Ausgaben befinden sich die Pfade zu den Bibliotheken, die executables aufrufen, in Aufrufen an open()
. Ist dies der Systemaufruf, der von ausführbaren Dateien verwendet wird, die dynamisch verknüpft sind? Was ist dlopen()
? open()
ist kein Aufruf, von dem ich vermutet hätte, dass er bei der Ausführung von Programmen eine Rolle spielt.
23
ld-linux
vom Kernel als Teil desexecve
Systemaufrufs zugeordnet werden.dlopen hat nichts mit Shared Libraries zu tun, wie Sie es sich vorstellen. Es gibt zwei Methoden zum Laden eines gemeinsam genutzten Objekts:
main
Funktion aufgerufen und der Prozessbereich der Anwendung so eingerichtet, dass die Anwendung die Funktionen der Bibliothek findet. Dazu müssenopen()
Sie zuerst den Lubrary und dannmmap()
einige Nachschlagetabellen einrichten .libdl
, mit dem Sie eine Verknüpfung herstellen möchten , von dem aus Sie dann (mit der ersten Methode) dasdlopen()
und aufrufen könnendlsym()
funktionen. Mit dlopen erhalten Sie ein Handle für die Bibliothek, das Sie dann mit dlsym verwenden können, um einen Funktionszeiger auf eine bestimmte Funktion zu erhalten. Diese Methode ist für den Programmierer viel komplizierter als die erste Methode (da Sie das Setup manuell ausführen müssen, anstatt dass der Linker es automatisch für Sie ausführt), und sie ist auch fragiler (da Sie die Kompilierung nicht erhalten) -time prüft, ob Sie Funktionen mit den richtigen Argumenttypen aufrufen, wie Sie es in der ersten Methode erhalten haben. Der Vorteil besteht jedoch darin, dass Sie entscheiden können, welches gemeinsame Objekt zur Laufzeit geladen werden soll (oder sogar, ob es überhaupt geladen werden soll) Dies ist eine Schnittstelle für Plug-In-Funktionen. Schließlich ist die dlopen-Schnittstelle auch weniger portabel als die andere, da ihre Mechanik von der genauen Implementierung des dynamischen Linkers abhängt (daher libtools)libltdl
, die versucht, diese Unterschiede zu abstrahieren).quelle
Heutzutage verwenden die meisten Betriebssysteme die Methode für gemeinsam genutzte Bibliotheken, die Ende 1987 von SunOS-4.0 eingeführt wurde. Diese Methode basiert auf der Zuordnung des Speichers über mmap ().
In Anbetracht der Tatsache, dass Sun in den frühen 1990er Jahren sogar den alten a.out-basierten Code (Solaris war zu diesem Zeitpunkt bereits ELF-basiert) an die FreeBSD-Leute gespendet und diesen Code später an viele andere Systeme (einschließlich Linux) übergeben hat Vielleicht verstehen Sie, warum es keinen großen Unterschied zwischen Plattformen gibt.
quelle
ltrace -S
Die Analyse eines Minimalbeispiels zeigt, dassmmap
es in glibc 2.23 verwendet wirdIn glibc 2.23, Ubuntu 16.04, ausgeführt
latrace -S
auf einem Minimalprogramm, das verwendet wirddlopen
mit:zeigt an:
so sehen wir sofort, dass
dlopen
ruftopen
+mmap
.Das fantastische
ltrace
Tool verfolgt sowohl Bibliotheksaufrufe als auch Systemaufrufe und ist daher perfekt, um zu untersuchen, was in diesem Fall vor sich geht.Eine genauere Analyse zeigt, dass
open
der Dateideskriptor zurückgegeben wird3
(nächster freier nach stdin, out und err).read
verwendet dann diesen Dateideskriptor, aber die Argumente von TODO whymmap
sind auf vier beschränkt, und wir können nicht sehen, welches fd dort verwendet wurde, da dies das fünfte Argument ist .strace
bestätigt, wie erwartet, dass dies3
der Fall ist, und die Ordnung des Universums wird wiederhergestellt.Tapfere Seelen können sich auch in Glibc-Code wagen, aber ich konnte den
mmap
nach einem kurzen Grep nicht finden und bin faul.Getestet mit diesem Minimalbeispiel mit Build Boilerplate auf GitHub .
quelle
strace
meldet Systemaufrufe (dh Funktionen, die direkt vom Kernel implementiert werden). Dynamische Bibliotheken sind keine Kernelfunktion.dlopen
ist Teil der C-Bibliothek, nicht des Kernels. Die Implementierung vondlopen
will callopen
(das ist ein Systemaufruf), um die Bibliotheksdatei zu öffnen, damit sie gelesen werden kann.quelle
ltrace
.ltrace -S
ist perfekt das , wie es auch zeigt syscalls zu analysieren: unix.stackexchange.com/a/462710/32558