Dynamic-link library: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
EnzoBot (discussione | contributi)
m Collegamenti esterni: Componenti di Windows
 
(21 versioni intermedie di 9 utenti non mostrate)
Riga 1:
{{Notanota disambigua||DLL (disambigua)|redirect=DLL}}
{{F|informatica|settembre 2023}}
Una '''''dynamic-link library''''' (dalla [[lingua inglese]], tradotto in [[lingua italiana|italiano]] con '''libreria a collegamento dinamico'''), in [[informatica]], indica una [[libreria software]] che viene caricata dinamicamente in fase di esecuzione, invece di essere [[Linguaggio di programmazione#Collegamento (linking)|collegata]] staticamente a un eseguibile in fase di [[compilatore|compilazione]]. Queste librerie sono note con l'acronimo '''DLL''', che è l'[[estensione (file)|estensione]] del [[file]] che hanno nel [[sistema operativo]] [[Microsoft Windows]], o anche con il termine '''librerie condivise''' (da ''shared library'', usato nella letteratura dei sistemi [[Unix]]). Nei sistemi che usano [[Executable and linkable format|ELF]] come formato dei [[File eseguibile|file eseguibili]], come ad esempio [[Solaris (sistema operativo)|Solaris]] o [[Linux]], sono anche note come ".so", abbreviazione di ''Shared Object''.
{{Formato file
 
|nome = Dynamic-link library
== Vantaggi e svantaggi ==
|logo = <!-- solo nome file -->
La separazione del codice in librerie a collegamento dinamico permette di suddividere il codice eseguibile in parti concettualmente separate, che verranno caricate solo se effettivamente necessarie. Inoltre, una singola libreria, caricata in memoria, può essere utilizzata da più programmi, senza la necessità di essere nuovamente caricata, il che permette di risparmiare le risorse del sistema. Questo metodo di ''loading on demand'' consente, inoltre, installazioni parziali di un sistema software, in cui sono effettivamente presenti sulla memoria di massa solo le librerie associate alle funzioni che l'utente desidera utilizzare, come selezionate in fase di installazione.
|icona = <!-- solo nome file -->
 
|immagine = <!-- solo nome file -->
Un altro vantaggio è la possibilità di aggiornare un programma modificando solo le DLL: inserendo una versione diversa della DLL, che contiene ad esempio dei ''[[bug fix]]'', tutti i programmi che la usano saranno automaticamente "aggiornati" senza bisogno di essere ricompilati.
|didascalia =
 
|estensione =
Il principale svantaggio è legato al fatto che una nuova versione di una DLL potrebbe effettuare dei cosiddetti ''breaking changes'', in modo volontario o, inconsapevolmente, a causa di bug nella nuova versione. Un breaking change è un cambiamento critico nel comportamento del codice della funzione che la rende non più compatibile con le convenzioni in uso (ad esempio, una funzione che prima restituiva NULL in caso di errore nei parametri e che ora setta ''[[errno]]'' e restituisce un valore non nullo). Ancora più critico il caso in cui un programma di installazione sovrascriva una DLL con una versione più vecchia. Altri problemi possono verificarsi in ambiente [[Component Object Model#Inferno delle DLL|COM]]. Questi problemi, ben noti ai programmatori [[Windows]], sono raggruppati sotto il nome di ''DLL hell'' (''inferno delle DLL'').
|magic_number =MZ
 
|mime = application/vnd.microsoft.portable-executable
In alcuni sistemi operativi, tipicamente [[Unix]] e [[Unix-like]], è possibile far convivere versioni diverse, fra loro incompatibili, di una stessa libreria, purché siano singolarmente presenti sul [[file system]] in differenti [[Pathname|percorsi]] e sia possibile, in fase di collegamento del programma, l'identificazione della versione corretta di libreria da utilizzare. In questa maniera, i programmi collegati prima dell'installazione della nuova libreria possono continuare ad avvalersi della vecchia versione.<ref>[http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/HTML/AA-PS30D-TET1_html/peg5.html#version_check_at_load Sito HP, Manuale Digital Unix: Controllo versione librerie in fase di caricamento]</ref>
|uniform_type_identifier = com.microsoft.windows-dynamic-link-library
 
|typecode =
I [[sistema operativo|sistemi operativi]] di tipo Windows mantengono un [[Backup|back up]] delle DLL di sistema in un'apposita memoria [[cache]], nella [[directory|cartella]] nascosta <code>C:\windows\system32\dllcache</code>. Nella cartella <code>C:\windows\system32\dll</code> sono invece memorizzate le librerie in uso.
|sviluppatore = [[Microsoft]]
 
|proprietario =
== Le DLL in Microsoft Windows ==
|licenza =
 
|data_pubblicazione =
=== Struttura e funzionamento ===
|ultima_versione =
|data_ultima_versione =
|nota_ultima_versione =
|genere = [[Libreria condivisa]]
|compressione = <!-- inserire "lossy" o "lossless" -->
|estensione_di =
|esteso_a =
|standard =
|aperto = <!-- inserire "sì" o "si" -->
|sito = <!-- senza http:// -->
}}
[[File:20230601 18 27 54-Error while loading plugins.png|thumb|Messaggio di errore su un sistema [[Microsoft Windows]] dovuto ad un problema nel caricamento di alcune librerie condivise]]
 
QuantoIn segue[[informatica]] descriveil la'''''dynamic-link strutturalibrary''''' ed(in ilacronimo funzionamento di una'''DLL''', {{lett|libreria a collegamento dinamico}}) inè ambienteun Windows,[[Formato tuttaviadi ifile|formato]] concettidi espressi[[libreria sonocondivisa]] generalmenteutilizzato equivalenti in tutti inei [[sistemi che permettono l'usooperativi]] di librerie dinamiche[[Microsoft]].
 
UnaIn libreria[[Windows]] auna collegamentolibreria dinamicodinamica è a tutti gli effetti un codice eseguibile. Ogni [[file eseguibile]] (EXE o DLL) dispone di un [[punto d'ingresso]] (''entry point'') invocato dal sistema operativo subito dopo il caricamento. Per una DLL il punto d'ingresso è mappato per convenzione sulla [[funzione (informatica)|funzione]] <code>DllMain</code> (a discrezione, comunque, del [[compilatore]]).
 
La funzione <code>DllMain</code>, oltre che al caricamento della DLL, viene invocata anche allo scaricamento o quando un [[Thread (informatica)|thread]] viene creato o distrutto nel [[processo (informatica)|processo]] in cui la DLL risiede.
Line 25 ⟶ 37:
A differenza di un file EXE, la DLL deve uscire dall'entry point non appena ha terminato le inizializzazioni necessarie.
 
=== Struttura ===
 
Per semplificare, una libreria può essere pensata come una raccolta di funzioni. Ognuna di queste funzioni avrà il proprio indirizzo di base, calcolato come [[offset]] rispetto all'[[indirizzo di base]] assegnato dal sistema operativo durante il caricamento della libreria (vedi paragrafo successivo). Ciò che distingue una libreria dinamica è che queste funzioni possono essere ''esportate'', ovvero i loro nomi vengono posti in una lista in una sezione dell'eseguibile. Perciò è possibile determinare il punto di ingresso di una funzione con una ricerca testuale basata sul nome della funzione. Questa operazione è svolta dall'[[Windows API|API]] <code>GetProcAddress</code> che restituisce l'indirizzo della funzione il cui nome è passato come parametro.
 
=== Caricamento ===
Le librerie dinamiche vengono caricate dal sistema operativo all'interno dello [[spazio di memoria]] del processo che le ha richieste. In questo modo l'accesso al codice della DLL avrà [[Prestazioni (informatica)|prestazioni]] quasi equivalenti a quelle del codice dell'applicazione stessa o del codice delle librerie statiche (in seguito si vedrà perché ''quasi'' equivalenti).
 
Per evitare che il codice dell'applicazione e quello della DLL occupino la stessa posizione in memoria, il [[linker]] dovrà predisporre la DLL per la [[rilocazione]]. In pratica, il sistema operativo determina un'area di memoria disponibile e rimappa ogni riferimento alla memoria contenuto nel codice della DLL. Siccome quest'operazione richiede tempo, ogni DLL dispone di un proprio ''indirizzo di base'' ideale: la rilocazione sarà necessaria solo se a questo indirizzo predeterminato è già stata mappata una precedente DLL. Per specificare l'indirizzo ideale si può usare una [[regola empirica]], basata sulla lettera iniziale del nome della DLL, secondo la seguente tabella:
Le librerie dinamiche vengono caricate dal sistema operativo all'interno dello [[spazio di memoria]] del processo che le ha richieste. In questo modo l'accesso al codice della DLL avrà prestazioni quasi equivalenti a quelle del codice dell'applicazione stessa o del codice delle librerie statiche (in seguito si vedrà perché ''quasi'' equivalenti).
 
{| class="wikitable"
Per evitare che il codice dell'applicazione e quello della DLL occupino la stessa posizione in memoria, il [[linker]] dovrà predisporre la DLL per la [[rilocazione]]. In pratica, il sistema operativo determina un'area di memoria disponibile e rimappa ogni riferimento alla memoria contenuto nel codice della DLL. Siccome quest'operazione richiede tempo, ogni DLL dispone di un proprio ''indirizzo di base'' ideale: la rilocazione sarà necessaria solo se a questo indirizzo predeterminato è già stata mappata una precedente DLL. Per specificare l'indirizzo ideale si può usare una regola empirica, basata sulla lettera iniziale del nome della DLL, secondo la seguente tabella:
 
{| border=1 cellspacing=0
!|Lettera iniziale!!Indirizzo di base
|-
|A-CA–C||<code>0x60000000 </code>
|-
|D-FD–F||<code>0x61000000 </code>
|-
|G-IG–I||<code>0x62000000 </code>
|-
|J-LJ–L||<code>0x63000000 </code>
|-
|M-OM–O||<code>0x64000000 </code>
|-
|P-RP–R||<code>0x65000000 </code>
|-
|S-US–U||<code>0x66000000 </code>
|-
|V-XV–X||<code>0x67000000 </code>
|-
|Y-ZY–Z||<code>0x68000000 </code>
|}
 
=== Collegamento ad un eseguibile ===
 
Il collegamento di un eseguibile a una libreria dinamica avviene durante l'esecuzione (a ''run time'') e avviene tramite l'API <code>LoadLibrary</code>, che accetta in [[input]] il nome della libreria. Ad esempio, <code>LoadLibrary(_T("MyLib.dll"))</code> caricherà all'interno dello spazio di memoria dell'applicazione la DLL <code>MyLib.dll</code>.
 
Il collegamento può essere di due tipi: esplicito o implicito.
 
==== Collegamento esplicito ====
 
Il collegamento esplicito viene gestito direttamente dal codice del programma con l'utilizzo delle due API <code>LoadLibrary</code> e <code>GetProcAddress</code> precedentemente descritte. Se si utilizza il [[linguaggio C]] si allocherà un [[puntatore (programmazione)|puntatore]] alla funzione specificata nel quale, al momento di utilizzare la funzione richiesta, si caricherà l'indirizzo con <code>GetProcAddress</code>. Questa tecnica permette di gestire in modo appropriato la condizione nella quale una DLL richiesta non è presente nel sistema, ma in generale è più macchinosa perché richiede l'utilizzo ''esplicito'' delle due API. Questa tecnica è indispensabile usando alcuni linguaggi di programmazione, quali ad esempio [[Visual Basic]].
 
==== Collegamento implicito ====
 
Il collegamento implicito è gestito direttamente dal linker in fase di compilazione, ed è usato quando si assume che una DLL sia sempre presente nel sistema. Ogni volta che nel codice sorgente è richiamata una funzione contenuta in una DLL, il linker collegherà la chiamata a funzione ad una funzione ''stub'', ovvero ad una funzione fittizia. All'interno dell'eseguibile vi sarà una tabella contenente gli ''stub'' a tutte le funzioni di DLL richieste. In fase di caricamento dell'eseguibile, il sistema operativo caricherà in automatico tutte le DLL richieste e mapperà ogni ''stub'' al punto di ingresso della relativa funzione nella relativa DLL. Se una DLL (o anche una singola funzione in una DLL) richiesta non viene trovata il sistema operativo bloccherà l'avvio del programma con un messaggio di errore.
 
L'utilizzo del collegamento implicito ha uno svantaggio in termini di prestazioni, perché ogni volta che viene richiamata una funzione contenuta in una DLL vi è un doppio salto a funzione: prima allo stub e poi all'indirizzo della funzione; l'[[overhead]] generato è in realtà trascurabile.
 
==== Collegamento implicito ritardato ====
Una variante al collegamento implicito prevista da alcuni compilatori è il ''collegamento ritardato''. In questo caso viene utilizzato uno ''stub'' speciale, che non viene mappato al caricamento dal sistema operativo. Questo ''stub'' invece, la prima volta che verrà invocato, si mapperà automaticamente (con la tecnica del collegamento esplicito) alla funzione della DLL. Questa tecnica ha il vantaggio di non richiedere la presenza della DLL per il caricamento dell'eseguibile, insieme alla comodità di non dover caricare esplicitamente da codice la libreria.
 
Una variante al collegamento implicito prevista da alcuni compilatori è il ''collegamento ritardato''. In questo caso viene utilizzato uno ''stub'' speciale, che non viene mappato al caricamento dal sistema operativo. Questo ''stub'' invece, la prima volta che verrà invocato, si mapperà automaticamente (con la tecnica del collegamento esplicito) alla funzione della DLL. Questa tecnica ha il vantaggio di non richiedere la presenza della DLL per il caricamento dell'eseguibile, insieme alla comodità di non dover caricare esplicitamente da codice la libreria
 
== Note ==
Line 81 ⟶ 87:
 
== Voci correlate ==
* [[Libreria (software)]]
* [[Linking]]
* [[Linguaggio di programmazione#Collegamento (linking)]]
* [[Executable and linkable format]]
* [[Ldd (Unix)]]
* [[Portable Executable]]
 
== Collegamenti esterni ==
* {{Collegamenti esterni}}
* {{cita web|http://www.negusweb.it/wiki/Panoramica_completa_sulle_DLL:_implementazione_ed_uso_in_ambiente_unmanaged_e_managed|Panoramica sulle DLL}}
* {{FOLDOC|Dynamically Linked Library|Dynamically Linked Library}}
* {{cita web | 1 = http://www.negusweb.it/wiki/Panoramica_completa_sulle_DLL:_implementazione_ed_uso_in_ambiente_unmanaged_e_managed | 2 = Panoramica completa sulle DLL: implementazione ed uso in ambiente unmanaged e managed | accesso = 19 marzo 2009 | dataarchivio = 16 novembre 2012 | urlarchivio = https://web.archive.org/web/20121116022306/http://www.negusweb.it/wiki/Panoramica_completa_sulle_DLL:_implementazione_ed_uso_in_ambiente_unmanaged_e_managed | urlmorto = sì }}
* {{cita web|https://blackwolf96blog.wordpress.com/2010/08/05/videoguida-come-creare-e-importare-una-dll-in-vb-2008/|Creare una DLL in Visual Basic 2008}}
* {{cita web
|url=https://people.redhat.com/drepper/dsohowto.pdf
|titolo=How to write shared libraries
|accesso=1º giugno 2008
|formato=PDF
|lingua=en
|autore=Ulrich Drepper
|data=20 agosto 2006
}}
 
{{Estensioni}}
{{Componenti di Windows}}
{{Portale|informatica|Microsoft}}
 
[[Categoria:Librerie software]]