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

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


Sono stato coinvolto in alcuni dibattiti riguardo alle librerie in Linux e vorrei confermare alcune cose.


È a mia conoscenza (correggimi se sbaglio e modificherò il mio post in seguito), che ci sono due modi per utilizzare le librerie durante la creazione di un'applicazione:



  1. Librerie statiche (file .a):al momento del collegamento, una copia dell'intera libreria viene inserita nell'applicazione finale in modo che le funzioni all'interno della libreria siano sempre disponibili per l'applicazione chiamante

  2. Oggetti condivisi (file .so):al momento del collegamento, l'oggetto viene semplicemente verificato rispetto alla sua API tramite il file di intestazione (.h) corrispondente. La libreria non viene effettivamente utilizzata fino al runtime, dove è necessario.


L'ovvio vantaggio delle librerie statiche è che consentono all'intera applicazione di essere autonoma, mentre il vantaggio delle librerie dinamiche è che il file ".so" può essere sostituito (es:nel caso debba essere aggiornato per motivi di sicurezza bug) senza richiedere la ricompilazione dell'applicazione di base.


Ho sentito alcune persone fare una distinzione tra oggetti condivisi e librerie collegate dinamiche (DLL), anche se sono entrambi file ".so". C'è qualche distinzione tra oggetti condivisi e DLL quando si tratta di sviluppo C/C++ su Linux o qualsiasi altro sistema operativo conforme a POSIX (es:MINIX, UNIX, QNX, ecc.)? Mi è stato detto che una differenza fondamentale (finora) è che gli oggetti condivisi vengono utilizzati solo in fase di esecuzione, mentre le DLL devono essere aperte prima utilizzando la chiamata dlopen() all'interno dell'applicazione.


Infine, ho anche sentito alcuni sviluppatori menzionare "archivi condivisi", che, a mio avviso, sono anche librerie statiche stesse, ma non vengono mai utilizzate direttamente da un'applicazione. Invece, altre librerie statiche si collegheranno agli "archivi condivisi" per estrarre alcune (ma non tutte) funzioni/risorse dall'archivio condiviso nella libreria statica in fase di creazione.


Grazie a tutti in anticipo per l'assistenza.


Aggiorna



Nel contesto in cui mi sono stati forniti questi termini, si trattava effettivamente di termini errati usati da un team di sviluppatori Windows che dovevano imparare Linux. Ho provato a correggerli, ma le norme linguistiche (errate) sono rimaste.



  1. Oggetto condiviso:una libreria che viene automaticamente collegata a un programma all'avvio del programma ed esiste come file autonomo. La libreria è inclusa nell'elenco dei collegamenti in fase di compilazione (es:LDOPTS+=-lmylib per un file di libreria denominato mylib.so ). La libreria deve essere presente in fase di compilazione e all'avvio dell'applicazione.

  2. Libreria statica:una libreria che viene unita al programma stesso in fase di compilazione per una singola applicazione (più grande) contenente il codice dell'applicazione e il codice della libreria che viene automaticamente collegato a un programma quando il programma viene compilato, e il finale binario contenente sia il programma principale che la libreria stessa esiste come un unico file binario autonomo. La libreria è inclusa nell'elenco dei collegamenti in fase di compilazione (es:LDOPTS+=-lmylib per un file di libreria denominato mylib.a). La libreria deve essere presente in fase di compilazione.

  3. DLL:essenzialmente uguale a un oggetto condiviso, ma invece di essere inclusa nell'elenco dei collegamenti in fase di compilazione, la libreria viene caricata tramite dlopen() /dlsym() comandi in modo che la libreria non debba essere presente in fase di compilazione per la compilazione del programma. Inoltre, la libreria non deve essere presente (necessariamente) all'avvio dell'applicazione o in fase di compilazione , in quanto al momento è necessario solo il dlopen /dlsym le chiamate vengono effettuate.

  4. Archivio condiviso:essenzialmente uguale a una libreria statica, ma viene compilato con i flag "export-shared" e "-fPIC". La libreria è inclusa nell'elenco dei collegamenti in fase di compilazione (es:LDOPTS+=-lmylibS per un file di libreria denominato mylibS.a ). La distinzione tra i due è che questo flag aggiuntivo è richiesto se un oggetto condiviso o una DLL vuole collegare staticamente l'archivio condiviso nel proprio codice ED essere in grado di rendere disponibili le funzioni nell'oggetto condiviso ad altri programmi, invece di usarle semplicemente interno alla DLL. Questo è utile nel caso in cui qualcuno ti fornisca una libreria statica e desideri riconfezionarla come SO. La libreria deve essere presente in fase di compilazione.


Aggiornamento aggiuntivo


La distinzione tra "DLL " e "shared library " era solo un linguaggio colloquiale (pigro, impreciso) nell'azienda in cui lavoravo all'epoca (gli sviluppatori Windows sono stati costretti a passare allo sviluppo di Linux e il termine si è bloccato), aderendo alle descrizioni sopra riportate.


Inoltre, il finale "S " letterale dopo il nome della libreria, nel caso di "archivi condivisi" era solo una convenzione utilizzata in quella società e non nel settore in generale.


Risposte:


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


Sono infatti 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 presenti. 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 appena usciti dal compilatore, proprio come quelli che stai creando tu stesso 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 allo stesso modo.