Frage

Ich höre oft die Begriffe "statisch verknüpft" und "dynamisch verknüpft", oft in Bezug auf den Code, der in geschriebener Code geschrieben wurde C, C ++ oder C#. Worüber genau sprechen sie und worüber verknüpfen sie?

War es hilfreich?

Lösung

Es gibt zwei Phasen (in den meisten Fällen diskontierten interpretierten Code), um vom Quellcode (was Sie schreiben) zu ausführbarem Code (was Sie ausführen).

Die erste Kompilierung, die den Quellcode in Objektmodule verwandelt.

Die zweite Verknüpfung ist das, was Objektmodule mit einer ausführbaren Datei kombiniert.

Die Unterscheidung wird unter anderem ermöglicht, in der Bibliotheken von Drittanbietern in Ihre ausführbare Datei aufgenommen zu werden, ohne dass Sie ihren Quellcode (z. C und Assembly -Code zum Beispiel) und dann alle miteinander verbinden.

Wenn du statisch Verknüpfen Sie eine Datei in eine ausführbare Datei, der Inhalt dieser Datei ist zum Verknüpfungszeit enthalten. Mit anderen Worten, der Inhalt der Datei wird physisch in die ausführende Datei eingefügt, die Sie ausführen.

Wenn Sie verlinken dynamisch, Ein Zeiger auf die Datei, die in (z. B. dem Dateinamen der Datei) verknüpft ist, ist in der ausführbaren Datei enthalten und der Inhalt dieser Datei ist nicht zum Verknüpfungszeit enthalten. Es ist nur dann, wenn Sie später Lauf Die ausführbare Datei, dass diese dynamisch verknüpften Dateien eingekauft werden und nur in die In-Memory-Kopie der ausführbaren Datei gekauft werden, nicht in der Festplatte.

Es handelt sich im Grunde genommen um eine Methode zur Verknüpfung der Verknüpfung. Es gibt eine gleichmäßige mehr Aufgeschobene Methode (die verspätete Bindung für einige Systeme genannt), die die dynamisch verknüpfte Datei nicht einbringt, wenn Sie tatsächlich versuchen, eine Funktion darin aufzurufen.

Statisch verknüpfte Dateien sind zum Linkzeit für die ausführbare Datei "gesperrt", sodass sie sich nie ändern. Eine dynamisch verknüpfte Datei, auf die eine ausführbare Datei verwiesen wird, kann sich nur durch Austausch der Datei auf der Festplatte ändern.

Dies ermöglicht die Aktualisierung der Funktionalität, ohne den Code neu zu verbinden. Der Loader ist jedes Mal, wenn Sie ihn ausführen, wieder an.

Dies ist sowohl gut als auch schlecht - einerseits ermöglicht es einfachere Updates und Fehlerbehebungen, andererseits kann es dazu führen, dass Programme zur Funktionsweise nicht mehr funktionieren, wenn die Updates nicht kompatibel sind - dies ist manchmal für die gefürchtete "DLL Hell" verantwortlich Erwähnen Sie, dass Anwendungen unterbrochen werden können, wenn Sie eine dynamisch verknüpfte Bibliothek durch eine nicht kompatibele Bibliothek ersetzen (Entwickler, die dies tun, sollten übrigens erwartet werden, dass sie niedergeschlagen und stark bestraft werden).


Als an Beispiel, Schauen wir uns den Fall eines Benutzer an, der ihre zusammenstellt main.c Datei für statische und dynamische Verknüpfung.

Phase     Static                    Dynamic
--------  ----------------------    ------------------------
          +---------+               +---------+
          | main.c  |               | main.c  |
          +---------+               +---------+
Compile........|.........................|...................
          +---------+ +---------+   +---------+ +--------+
          | main.o  | | crtlib  |   | main.o  | | crtimp |
          +---------+ +---------+   +---------+ +--------+
Link...........|..........|..............|...........|.......
               |          |              +-----------+
               |          |              |
          +---------+     |         +---------+ +--------+
          |  main   |-----+         |  main   | | crtdll |
          +---------+               +---------+ +--------+
Load/Run.......|.........................|..........|........
          +---------+               +---------+     |
          | main in |               | main in |-----+
          | memory  |               | memory  |
          +---------+               +---------+

Sie können im statischen Fall sehen, dass das Hauptprogramm und die C -Laufzeitbibliothek zum Verknüpfungszeit (von den Entwicklern) miteinander verknüpft sind. Da der Benutzer die ausführbare Datei in der Regel nicht neu verknüpfen kann, hängen sie mit dem Verhalten der Bibliothek fest.

Im dynamischen Fall ist das Hauptprogramm mit der C -Laufzeit -Importbibliothek verknüpft (etwas, das erklärt, was sich in der dynamischen Bibliothek befindet, aber eigentlich nicht definieren es). Auf diese Weise kann der Linker verlinken, obwohl der tatsächliche Code fehlt.

Zur Laufzeit führt der Betriebssystemlader mit der C -Laufzeit -DLL (Dynamic Link Library oder Shared Library oder einer anderen Nomenklatur) eine verspätete Verknüpfung des Hauptprogramms durch.

Der Eigentümer der C -Laufzeit kann jederzeit in einer neuen DLL fallen, um Updates oder Fehlerbehebungen bereitzustellen. Wie bereits erwähnt, hat dies sowohl Vor- als auch Nachteile.

Andere Tipps

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

Wenn Sie einen C -Code (zum Beispiel) kompilieren, wird er in die Maschinensprache übersetzt. Nur eine Folge von Bytes, die beim Ausführen den Prozessor dazu veranlassen, "Gedächtnis zu lesen, Speicher zu schreiben, so etwas. Dieses Zeug wird in Objektdateien (.o) gespeichert.

Jetzt, vor langer Zeit, haben Informatiker dieses "Unterroutine" -Ding erfunden. Führen Sie-diese Chunk-of-Code-and-Return-hier aus. Es dauerte nicht lange, bis sie merkten, dass die nützlichsten Unterprogramme an einem besonderen Ort gespeichert und von jedem Programm verwendet werden konnten, das sie benötigte.

Jetzt müssten Programmierer in den frühen Tagen die Speicheradresse, in der sich diese Unterprogramme befanden, einstauchen. Etwas wie CALL 0x5A62. Dies war mühsam und problematisch, wenn diese Speicheradressen jemals geändert werden müssen.

Der Prozess wurde also automatisiert. Sie schreiben ein Programm, das anruft printf(), und der Compiler kennt die Speicheradresse von nicht printf. Also schreibt der Compiler nur CALL 0x0000, und fügt der Objektdatei einen Hinweis hinzu: "Muss diesen 0x0000 durch den Speicherort von ersetzen printf".

Statische Verknüpfung bedeutet, dass das Linker -Programm (die GNU One genannt wird ld) fügt hinzu printfDer Maschinencode direkt zu Ihrer ausführbaren Datei und ändert den 0x0000 an die Adresse von printf. Dies geschieht, wenn Ihre ausführbare Datei erstellt wird.

Dynamische Verknüpfung bedeutet, dass der obige Schritt nicht stattfindet. Die ausführbare Datei still hat eine Notiz mit der Aufschrift "muss 0x000 durch den Speicherort von printf ersetzen". Der Lader des Betriebssystems muss den Printf -Code ermitteln, in den Speicher laden und die Anrufadresse korrigieren. Jedes Mal, wenn das Programm ausgeführt wird.

Es ist üblich, dass Programme einige Funktionen aufrufen, die statisch verknüpft sind (Standardbibliotheksfunktionen wie printf sind normalerweise 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 Unterschiede zwischen Betriebssystemen. Aber da du nicht gefragt hast, werde ich das hier beenden.

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

Weil keines der oben genannten Beiträge Zeigen Sie tatsächlich wie Um etwas statisch zu verknüpfen und zu sehen, dass Sie es richtig gemacht haben, werde ich dieses Problem ansprechen:

Ein einfaches C -Programm

#include <stdio.h>

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

Dynamisch das C -Programm verknüpfen

gcc simpleprog.c -o simpleprog

Und Renn file auf der Binärdatei:

file simpleprog 

Und das wird zeigen, dass es dynamisch etwas miteinander verbunden ist:

"simpleprog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xf715572611a8b04f686809d90d1c0d75c6028f0f, not stripped"

Lassen Sie uns stattdessen das Programm dieses Mal statisch verknüpfen:

gcc simpleprog.c -static -o simpleprog

Das Ausführen von Datei in dieser statisch verknüpften Binärdatei zeigt:

file simpleprog 

"SimpleProg: ELF 64-Bit LSB Executable, x86-64, Version 1 (GNU/Linux), statisch verknüpft, für GNU/Linux 2.6.26, BuildID [SHA1] = 0x8c0b12250801C5A7C7434647b7dc65a644d6132b, nicht abgerissen"

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

Zum Glück wie viele eingebettete C -Bibliotheken mögen musl Bieten Sie statische Verknüpfungsoptionen für fast alle an wenn nicht alle ihrer Bibliotheken.

Jetzt strace Die Binärdatei, die Sie erstellt haben, und Sie können sehen, dass vor Beginn des Programms keine Bibliotheken zugegriffen werden:

strace ./simpleprog

Vergleichen Sie nun mit der Ausgabe von strace Im dynamisch verknüpften Programm und Sie werden sehen, dass die Strace der staatlich verknüpften Version viel kürzer ist!

(Ich weiß nicht C#, aber es ist interessant, ein statisches Verknüpfungskonzept für eine VM -Sprache zu haben)

Beim Dynamic -Verknüpfung wird wissen, wie Sie eine erforderliche Funktionalität finden, die Sie nur von Ihrem Programm referenzieren können. Ihre Sprachlaufzeit oder Betriebssystemsuche nach einem Code im Dateisystem, des Netzwerks oder des kompilierten Code -Cache, der der Referenz entspricht, und dann mehrere Maßnahmen ergriffen, um ihn in Ihr Programmbild in den Speicher zu integrieren, z. B. Umzug. Sie sind alle zur Laufzeit fertig. Es kann entweder manuell oder vom Compiler durchgeführt werden. Es besteht die Möglichkeit, mit dem Risiko zu aktualisieren (nämlich die Hölle).

Die statische Verknüpfung erfolgt zur Kompilierung, dass Sie dem Compiler mitteilen, wo sich alle funktionalen Teile befinden, und sie anweisen, sie zu integrieren. Es gibt keine Suche, keine Unklarheit, keine Fähigkeit, ohne Neukompilien zu aktualisieren. Alle Ihre Abhängigkeiten sind physisch mit Ihrem Programmbild.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top