c# - library - static linking vs dynamic linking




Was bedeuten "statisch verknüpft" und "dynamisch verknüpft"? (4)

(Ich kenne C # nicht, aber es ist interessant, ein statisches Linking-Konzept für eine VM-Sprache zu haben)

Bei der dynamischen Verknüpfung müssen Sie wissen, wie Sie eine erforderliche Funktionalität finden, die Sie nur aus Ihrem Programm beziehen. Ihre Sprachlaufzeit oder Ihr Betriebssystem sucht nach einem Code im Dateisystem-, Netzwerk- oder kompilierten Code-Cache, der mit der Referenz übereinstimmt, und nimmt dann mehrere Maßnahmen vor, um sie in das Programmbild im Speicher zu integrieren, z. Sie sind alle zur Laufzeit fertig. Dies kann entweder manuell oder durch den Compiler geschehen. Es gibt die Möglichkeit, mit einem Risiko der Unordnung zu aktualisieren (DLL DLL Hölle).

Die statische Verknüpfung erfolgt zur Kompilierungszeit, indem Sie dem Compiler mitteilen, wo sich alle funktionalen Teile befinden, und ihn anweisen, sie zu integrieren. Es gibt keine Suche, keine Mehrdeutigkeit, keine Möglichkeit, ohne eine Neukompilierung zu aktualisieren. Alle Ihre Abhängigkeiten sind physikalisch eins mit Ihrem Programmbild.

Ich höre oft die Begriffe "statisch verknüpft" und "dynamisch verknüpft", oft in Bezug auf Code in C , C++ oder C# , aber ich weiß auch nicht viel über beides. Worüber genau sprechen sie und was verbinden sie?


Da keiner der oben genannten Posts tatsächlich zeigt, wie man etwas statisch verknüpft und sieht, dass du es richtig gemacht hast, werde ich dieses Problem angehen:

Ein einfaches C-Programm

#include <stdio.h>

int main(void)
{
    printf("This is a string\n");
    return 0;
}

Verknüpfen Sie das C-Programm dynamisch

gcc simpleprog.c -o simpleprog

Und file auf der Binärdatei ausführen:

file simpleprog 

Und das wird zeigen, dass es dynamisch verknüpft ist mit:

"simpleprog: ELF 64-bit LSB ausführbare Datei, x86-64, Version 1 (SYSV), dynamisch verlinkt (verwendet gemeinsame libs), für GNU / Linux 2.6.26, BuildID [sha1] = 0xf715572611a8b04f686809d90d1c0d75c6028f0f, nicht entfernt"

Lassen Sie uns stattdessen dieses Programm statisch verknüpfen:

gcc simpleprog.c -static -o simpleprog

Wenn Sie eine Datei auf dieser statisch verknüpften Binärdatei ausführen, wird Folgendes angezeigt:

file simpleprog 

"simpleprog: ELF 64-bit LSB ausführbare Datei, x86-64, Version 1 (GNU / Linux), statisch verknüpft, für GNU / Linux 2.6.26, BuildID [sha1] = 0x8c0b12250801c5a7c7434647b7dc65a644d6132b, nicht entfernt"

Und Sie können sehen, dass es glücklich statisch verbunden ist. Leider sind jedoch nicht alle Bibliotheken einfach auf diese Art und Weise statisch miteinander zu verknüpfen und erfordern möglicherweise einen längeren Einsatz von libtool oder die Verknüpfung von Objektcode und C-Bibliotheken von Hand.

Zum Glück bieten viele eingebettete C-Bibliotheken wie musl statische Verknüpfungsoptionen für fast alle, wenn nicht alle ihrer Bibliotheken.

Jetzt strace die von Ihnen erstellte Binärdatei und Sie können sehen, dass vor dem Programmstart keine Bibliotheken aufgerufen werden:

strace ./simpleprog

Vergleichen Sie nun mit der Ausgabe von strace auf dem dynamisch verknüpften Programm und Sie werden feststellen, dass die strace der statisch verknüpften Version viel kürzer ist!


Ich denke, eine gute Antwort auf diese Frage sollte erklären, was Verknüpfung ist .

Wenn Sie beispielsweise einen C-Code kompilieren, wird dieser in die Maschinensprache übersetzt. Nur eine Folge von Bytes, die, wenn sie ausgeführt wird, den Prozessor dazu bringt, Add, Subtract, Compare, "Goto", Speicher zu lesen, Speicher zu schreiben, diese Art von Dingen. Dieses Zeug wird in Objektdateien (.o) gespeichert.

Vor langer Zeit haben Computerwissenschaftler diese "Subroutine" erfunden. Execute-this-chunk-of-code-und-zurück-hier. Es dauerte nicht lange, bis sie feststellten, dass die nützlichsten Unterprogramme an einem besonderen Ort gespeichert und von jedem Programm verwendet werden konnten, das sie benötigte.

In der Anfangszeit mussten Programmierer die Speicheradresse eingeben, in der sich diese Subroutinen befanden. So etwas wie CALL 0x5A62 . Dies war mühsam und problematisch, sollten diese Speicheradressen jemals geändert werden müssen.

Also, der Prozess wurde automatisiert. Sie schreiben ein Programm, das printf() aufruft, und der Compiler kennt die Speicheradresse von printf . Der Compiler schreibt also einfach CALL 0x0000 und fügt der Objektdatei eine Notiz hinzu, die besagt, dass "diese 0x0000 durch den Speicherort von printf ersetzen muss".

Statische Verknüpfung bedeutet, dass das Linker-Programm (der GNU-Name heißt ld ) printf Maschinencode direkt zu Ihrer ausführbaren Datei hinzufügt und den Wert 0x0000 in die Adresse von printf ändert. Dies geschieht, wenn Ihre ausführbare Datei erstellt wird.

Dynamische Verknüpfung bedeutet, dass der obige Schritt nicht stattfindet. Die ausführbare Datei hat immer noch eine Notiz, die besagt "muss 0x000 durch den Speicherort von printf ersetzen". Das Ladeprogramm des Betriebssystems muss den printf-Code finden, in den Speicher laden und die CALL-Adresse jedes Mal korrigieren, wenn das Programm ausgeführt wird .

Es ist üblich, dass Programme einige Funktionen aufrufen, die statisch verknüpft sind (Standardbibliotheksfunktionen wie printf sind in der Regel statisch verknüpft) und andere Funktionen, die dynamisch verknüpft sind. Die statischen werden "Teil der ausführbaren Datei" und die dynamischen "beitreten", wenn die ausführbare Datei ausgeführt wird.

Beide Methoden haben Vor- und Nachteile, und es gibt Unterschiede zwischen den Betriebssystemen. Aber da du nicht gefragt hast, werde ich das hier beenden.


Statisch verknüpfte Bibliotheken werden zur Kompilierungszeit verknüpft. Dynamisch verknüpfte Bibliotheken werden zur Laufzeit geladen. Die statische Verknüpfung baktet das Bibliotheksbit in Ihre ausführbare Datei. Die dynamische Verknüpfung backt nur einen Verweis auf die Bibliothek; Die Bits für die dynamische Bibliothek existieren an anderer Stelle und könnten später ausgetauscht werden.







dynamic-linking