GNU/Linux >> Linux Esercitazione >  >> Linux

Differenza tra oggetti condivisi (.so), librerie statiche (.a) e DLL (.so)?

Una libreria statica(.a) è una libreria che può essere collegata direttamente all'eseguibile finale prodotto dal linker, è contenuta in esso e non è necessario avere la libreria nel sistema in cui verrà distribuito l'eseguibile.

Una libreria condivisa (.so) è una libreria collegata ma non incorporata nell'eseguibile finale, quindi verrà caricata all'avvio dell'eseguibile e dovrà essere presente nel sistema in cui viene distribuito l'eseguibile.

Una libreria di collegamenti dinamici su windows(.dll) è come una libreria condivisa (.so) su Linux ma ci sono alcune differenze tra le due implementazioni relative al sistema operativo (Windows vs Linux):

Una DLL può definire due tipi di funzioni:esportate e interne. Le funzioni esportate devono essere chiamate da altri moduli, nonché dall'interno della DLL in cui sono definite. Le funzioni interne sono in genere destinate a essere chiamate solo dall'interno della DLL in cui sono definite.

Un SO library su Linux non necessita di una dichiarazione di esportazione speciale per indicare i simboli esportabili, poiché tutti i simboli sono disponibili per un processo di interrogazione.


Ho sempre pensato che DLL e oggetti condivisi siano solo termini diversi per la stessa cosa - Windows li chiama DLL, mentre sui sistemi UNIX sono oggetti condivisi, con il termine generale - libreria collegata dinamicamente - che copre entrambi (anche la funzione di aprire un .so su UNIX si chiama dlopen() dopo 'libreria dinamica').

In effetti sono collegati solo all'avvio dell'applicazione, tuttavia la tua nozione di verifica rispetto al file di intestazione non è corretta. Il file di intestazione definisce i prototipi necessari per compilare il codice che utilizza la libreria, ma al momento del collegamento il linker guarda all'interno della libreria stessa per assicurarsi che le funzioni di cui ha bisogno siano effettivamente lì. Il linker deve trovare i corpi della funzione da qualche parte al momento del collegamento o genererà un errore. Lo fa ANCHE in fase di esecuzione, perché come giustamente fai notare la libreria stessa potrebbe essere cambiata da quando il programma è stato compilato. Questo è il motivo per cui la stabilità dell'ABI è così importante nelle librerie della piattaforma, poiché la modifica dell'ABI è ciò che interrompe i programmi esistenti compilati rispetto alle versioni precedenti.

Le librerie statiche sono solo pacchetti di file oggetto direttamente dal compilatore, proprio come quelli che stai costruendo come parte della compilazione del tuo progetto, quindi vengono inseriti e inviati al linker esattamente nello stesso modo, e i bit inutilizzati sono caduto esattamente nello stesso modo.


Posso approfondire i dettagli delle DLL in Windows per aiutare a chiarire questi misteri ai miei amici qui in *NIX-land...

Una DLL è come un file oggetto condiviso. Entrambe sono immagini, pronte per essere caricate in memoria dal caricatore di programmi del rispettivo sistema operativo. Le immagini sono accompagnate da vari bit di metadati per aiutare i linker e i caricatori a creare le associazioni necessarie e utilizzare la libreria di codice.

Le DLL di Windows hanno una tabella di esportazione. Le esportazioni possono essere per nome o per posizione della tabella (numerica). Quest'ultimo metodo è considerato "vecchia scuola" ed è molto più fragile:la ricostruzione della DLL e la modifica della posizione di una funzione nella tabella finiranno in un disastro, mentre non vi è alcun problema reale se il collegamento dei punti di ingresso è per nome. Quindi, dimenticalo come problema, ma tieni presente che è lì se lavori con codice "dinosauro" come librerie di fornitori di terze parti.

Le DLL di Windows sono create compilando e collegando, proprio come faresti per un EXE (applicazione eseguibile), ma la DLL non è pensata per essere autonoma, proprio come un SO è pensato per essere utilizzato da un'applicazione, tramite caricamento dinamico o mediante associazione in tempo di collegamento (il riferimento all'SO è incorporato nei metadati del file binario dell'applicazione e il programma di caricamento del sistema operativo caricherà automaticamente gli SO a cui si fa riferimento). Le DLL possono fare riferimento ad altre DLL, così come i SO possono fare riferimento ad altri SO.

In Windows, le DLL renderanno disponibili solo punti di ingresso specifici. Questi sono chiamati "esportazioni". Lo sviluppatore può utilizzare una speciale parola chiave del compilatore per rendere un simbolo visibile esternamente (ad altri linker e al caricatore dinamico), oppure le esportazioni possono essere elencate in un file di definizione del modulo che viene utilizzato al momento del collegamento quando la DLL stessa è in fase di creazione. La pratica moderna è decorare la definizione della funzione con la parola chiave per esportare il nome del simbolo. È anche possibile creare file di intestazione con parole chiave che dichiareranno quel simbolo come simbolo da importare da una DLL esterna all'unità di compilazione corrente. Cerca le parole chiave __declspec(dllexport) e __declspec(dllimport) per ulteriori informazioni.

Una delle caratteristiche interessanti delle DLL è che possono dichiarare una funzione di gestore standard "al caricamento/scaricamento". Ogni volta che la DLL viene caricata o scaricata, la DLL può eseguire un'inizializzazione o una pulizia, a seconda dei casi. Questo si adatta perfettamente all'avere una DLL come gestore di risorse orientato agli oggetti, come un driver di dispositivo o un'interfaccia a oggetti condivisi.

Quando uno sviluppatore desidera utilizzare una DLL già compilata, deve fare riferimento a una "libreria di esportazione" (*.LIB) creata dallo sviluppatore DLL quando ha creato la DLL oppure deve caricare esplicitamente la DLL in fase di esecuzione e richiedere il indirizzo del punto di ingresso per nome tramite i meccanismi LoadLibrary() e GetProcAddress(). La maggior parte delle volte, il collegamento a un file LIB (che contiene semplicemente i metadati del linker per i punti di ingresso esportati della DLL) è il modo in cui vengono utilizzate le DLL. Il caricamento dinamico è tipicamente riservato all'implementazione del "polimorfismo" o della "configurabilità di runtime" nei comportamenti del programma (accesso a componenti aggiuntivi o funzionalità definite in seguito, ovvero "plug-in").

Il modo in cui Windows fa le cose a volte può causare confusione; il sistema utilizza l'estensione .LIB per fare riferimento sia alle normali librerie statiche (archivi, come i file POSIX *.a) sia alle librerie "export stub" necessarie per associare un'applicazione a una DLL al momento del collegamento. Quindi, si dovrebbe sempre controllare se un file *.LIB ha un file *.DLL con lo stesso nome; in caso contrario, è probabile che il file *.LIB sia un archivio di libreria statica e non esporti i metadati di binding per una DLL.


Linux
  1. Differenza tra shell di accesso e shell non di accesso?

  2. La differenza tra [[ $a ==Z* ]] e [ $a ==Z* ]?

  3. Differenza tra le applicazioni Gtk e Qt?

  4. Differenza tra dimensione del blocco e dimensione del cluster?

  5. Differenza tra tubazioni ed espansione dei comandi?

Differenza tra firewall hardware condiviso e firewall hardware dedicato

Differenza tra apt e apt-get spiegato

Differenza tra utente Sudo e utente root?

Differenza tra Snat e Masquerade?

Convertire una libreria statica in una libreria condivisa?

Qual è la differenza tra chiamata di sistema e chiamata di libreria?