160 likes | 323 Views
DLL: Dynamic Linking Library. Librerie programmative. Raccolta di routine precompilate d’utilità per più programmi/applicazioni Precompilate = in formato eseguibile Contengono: codice, risorse, dati
E N D
Librerie programmative • Raccolta di routine precompilate d’utilità per più programmi/applicazioni • Precompilate = in formato eseguibile • Contengono: codice, risorse, dati • Per l’uso di una libreria in un programma, bisogna conoscere i prototipi (header) delle routine • Le librerie vengono distribuite con un file header che contiene i prototipi e viene importato nei programmi • In C/C++ la direttiva per importare un file header è #include • Per esempio: #include <stdio.h> • Per l’esecuzione del programma le librerie usate devono saranno collegate (linking) al codice eseguibile
Static/Dynamic linking • Static linking • Il collegamente avviene a compile-time • Il linker estrae le routine usate dalla libreria e le allega al codice eseguibile del programma • Esempio: librerie runtime del C (stdio.h, stdlib.h, …) • Esiste un’istanza delle routine per ogni programma che le usa • Dynamic linking libraries (DLL) • Il collegamento avviene a runtime • Il codice delle routine non è allegato al programma, ma viene caricato separatamente al momento dell’uso • Unica istanza sul disco • Unica istanza in memoria
Perché le DLL in Windows • Condivione di codice: risparmia spazio su disco e memoria per le applicazioni • Inizialmente scelto per permettere a Windows di lavorare con poca memoria, pur lanciando più programmi simultaneamente (multitasking) • Modularità • Fare una modifica al codice condiviso da più applicazioni impatta solo sulla DLL corrispondente (più semplice distribuire service pack) • Semplifica la distribuzione dei service-pack di aggiornamento del sistema • Estendibilità dinamica del sistema • È più semplice aggiungere nuovi moduli (pluging) per applicazioni preesistenti • Attenzione però… al problema del “DLL hell” • Conflitti fra diverse applicazioni che usano versioni differenti della stessa DLL
Ruolo delle DLL in Windows • Essere un contenitore di codice eseguibile riusabile • Esportare dati e codice contenuti ai processi che vogliono utilizzarli
Static linking (esempio) • Da Visual C++ 2005 Express Edition • New project • Impostare un progetto di tipo “Win32 console application” • Nel dialog “application settings” impostare l’opzione “Static library” • Per implementare una libreria statica occorrono: • File header che dichiara i prototipi delle funzioni esportate • File dell’implementazione corrispondente
Dynamic linking (esempio) • Da Visual C++ 2005 Express Edition • New project • Impostare un progetto di tipo “Win32 console application” • Nel dialog “application settings” impostare l’opzione “DLL” • Per implementare una DLL occorrono • File header che dichiara i prototipi delle funzioni esportate • File dell’implementazione corrispondente • File contenente l’entry point della DLL • Simile al main di un’applicazione, gestisce eventuali operazioni d’inizializzazione della DLL • (opzionale) file header che dichiara i prototipi delle funzioni non esportate • (opzionale) File dell’implementazione corrispondente • (opzionale) file def che specifica le funzioni da esportare
Esportare le funzioni • Metodo generale utilizzare un file .def (Module Definition file) • Metodo “Microsoft specific” Dichiarare le funzioni da esportare e importate rispettivamente con __declspec(dllexport) __declspec(dllimport)
Convenzioni di chiamata • Determinano il modo in cui i parametri sono depositati e letti dallo stack. • La convenzione di chiamata standard è __stdcall che corrisponde alle seguenti convenzioni: • La funzione chiamata ha la responsabilità di pulire lo stack • I parametri sono passati in ordine da destra verso sinistra • Il nome della funzione viene “decorato” per evitare di incappare in funzioni con lo stesso nome: • Carattere _ come prefisso e @ come suffisso, più il numero di byte dei parametri
Uso di una DLL (i/ii) • Caricamento in memoria in modalità load-time • Il programma utilizzatore include il file header che dichiara i prototipi delle funzioni esportate dalla DLL • Il programma utilizzatore viene collegato ad un file .lib generato in fase di creazione della DLL • Simile ad una libreria statica, ma contiene solo le informazioni per caricare la DLL (non l’implementazione delle funzioni esportate) • La DLL deve essere disponibile a runtime • Nella stessa cartella dell’applicazione • Nelle cartelle di sistema • Nelle cartelle specificate dalla variabile d’ambiente PATH
Uso di una DLL (ii/ii) • Caricamento in memoria in modalità run-time • Non è necessario includere alcun header, né collegare alcun file lib • Il caricamento viene gestito direttamente dal programma • Procedimento • Definire i prototipi da usare come puntatori a funzione • Caricare la DLL direttamente dal file system (LoadLibrary) • Estrarre le funzioni da usare dalla DLL (GetProcAddress) • Gestire gli errori di LoadLibrary e GetProcAddress • Rilasciare la libreria dopo l’uso (FreeLibrary)
Caricamento delle DLLLoad-time vs. Run-time • Con il caricamento run-time non c’è bisogno di avere la import library della DLL da usare • Bisogna comunque conoscere le funzioni da usare e i loro parametri • Però è possibile usare funzioni non esplicitamente documentate • Exception handling • Con il caricamento run-time è possibile gestire le eccezioni legate alla mancanza (o impossibilità di trovare) una DLL • Performance • Con il caricamento a load-time il codice è più snello e un po’ più veloce (non si invoca GetProcessAddress)
DLL entry-point • L’entry-point di una DLL è la funzione dllMain con tre parametri: • HANDLE hModule: riferimento alla DLL stessa • DWORD ul_reason_for_call: ragione della chiamata: • DLL_PROCESS_ATTACH: la DLL viene caricata da un nuovo processo • DLL_THREAD_ATTACH: la DLL viene acceduta da un altro thread di un processo • DLL_THREAD_DETACH: la DLL viene rilasciata da un thread • DLL_PROCESS_DETACH: la DLL viene rilasciata da un processo • LPVOID lpReserved: riservato per usi futuri
Gestione delle DLL in memoria • Una DLL viene caricata in RAM al primo accesso • Quando un processo carica la DLL nel suo spazio d’indirizzamento virtuale, inizializza un contatore di riferimenti alla DLL • L’accesso di un nuovo thread alla DLL o una chiamata di LoadLibrary() incrementa il contatore • La terminazione di un thread o l’invocazione di FreeLibrary() decrementa il contatore • Quando il processo termina (modalità load-time) o quando il contatore va a 0 (modalità run-time), la DLL viene scaricata dalla memoria virtuale del processo • La DLL viene scaricata dalla RAM quando nessun processo la sta più utilizzando
Visual C++ Express • È possibile istallare Visual C++ 2005 Express Edition e Microsoft Platform Software Development Kit (SDK), seguendo le istruzioni disponibili presso: http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/ Nota: bisogna scaricare 2,5 MB per inizializzare l'istallazione + altri 91 MB per completarla + circa 200MB per SDK.
Riferimenti • Pinardi, Aruanno, Bisiani. “Windows & .NET 2000 in Action” – Capitolo 7