Bibliotecă de legături dinamice
O bibliotecă cu legături dinamice (din engleză , tradusă în italiană cu bibliotecă cu legături dinamice ), în informatică , indică o bibliotecă software care este încărcată dinamic în timp de execuție, în loc să fie legată static de un executabil în timpul compilării . Aceste biblioteci sunt cunoscute cu acronimul DLL , care este extensia fișierului pe care îl au în sistemul de operare Microsoft Windows sau, de asemenea, cu termenul biblioteci partajate (din bibliotecă partajată , utilizat în literatura de sisteme Unix ). Pe sistemele care utilizează ELF ca format de fișier executabil , cum ar fiSolaris sau Linux , acestea sunt cunoscute și sub denumirea de „.so”, prescurtare pentru Shared Object .
Avantaje și dezavantaje
Separarea codului în biblioteci de legături dinamice vă permite să împărțiți codul executabil în părți conceptuale separate, care vor fi încărcate numai dacă sunt efectiv necesare. Mai mult, o singură bibliotecă, încărcată în memorie, poate fi utilizată de mai multe programe, fără a fi necesară reîncărcarea, ceea ce economisește resursele sistemului. Această metodă de încărcare la cerere permite, de asemenea, instalarea parțială a unui sistem software, în care doar bibliotecile asociate cu funcțiile pe care utilizatorul dorește să le utilizeze, așa cum sunt selectate în timpul fazei de instalare, sunt de fapt prezente pe memoria de masă.
Un alt avantaj este posibilitatea de a actualiza un program modificând doar DLL-urile: prin inserarea unei versiuni diferite a DLL, care conține, de exemplu, remedieri de erori , toate programele care îl utilizează vor fi automat „actualizate” fără a fi nevoie să fie recompilate.
Principalul dezavantaj este legat de faptul că o nouă versiune a unui DLL ar putea face așa-numitele modificări de rupere , fie în mod voluntar, fie, fără să știe, din cauza bug-urilor din noua versiune. O schimbare de rupere este o schimbare critică în comportamentul codului funcției care îl face să nu mai fie compatibil cu convențiile utilizate (de exemplu, o funcție care a returnat anterior NULL în cazul unei erori în parametri și care acum setează errno și returnează o valoare care nu este nulă). Și mai critic este cazul în care un program de instalare suprascrie un DLL cu o versiune mai veche. Alte probleme pot apărea în mediul COM . Aceste probleme, bine cunoscute programatorilor Windows , sunt grupate sub numele de Hell DLL (DLL Hell).
În unele sisteme de operare, de obicei Unix și Unix-like , este posibil să coexiste versiuni diferite, incompatibile ale aceleiași biblioteci, cu condiția să fie prezente individual pe sistemul de fișiere pe căi diferite și este posibil, atunci când conectați programul, „identificarea versiunii corecte a bibliotecii de utilizat. În acest fel, programele legate înainte de instalarea noii biblioteci pot continua să utilizeze versiunea veche. [1]
Sistemele de operare de tip Windows păstrează o copie de rezervă a DLL-urilor de sistem într-o memorie cache specială, în folderul ascuns C:\windows\system32\dllcache
. Bibliotecile utilizate sunt stocate în C:\windows\system32\dll
.
DLL-uri în Microsoft Windows
Structura și funcția
Următoarele descriu structura și funcționarea unei biblioteci de legături dinamice într-un mediu Windows, totuși conceptele exprimate sunt în general echivalente în toate sistemele care permit utilizarea bibliotecilor dinamice.
O bibliotecă de legături dinamice este efectiv un cod executabil. Fiecare fișier executabil (EXE sau DLL) are un punct de intrare (punct de intrare) invocat de sistemul de operare imediat după încărcare. Pentru un DLL, punctul de intrare este mapat în mod convențional la funcția DllMain
(la discreția compilatorului ).
Funcția DllMain
, pe lângă încărcarea DLL, este invocată și la descărcare sau atunci când un fir este creat sau distrus în procesul în care se află DLL.
Spre deosebire de un fișier EXE, DLL trebuie să părăsească punctul de intrare imediat ce a finalizat inițializările necesare.
Structura
Pentru a simplifica, o bibliotecă poate fi gândită ca o colecție de funcții. Fiecare dintre aceste funcții va avea propria adresă de bază, calculată ca un offset față de adresa de bază atribuită de sistemul de operare la încărcarea bibliotecii (vezi paragraful următor). Ceea ce distinge o bibliotecă dinamică este că aceste funcții pot fi exportate , adică numele lor sunt plasate într-o listă într-o secțiune a executabilului. Prin urmare, este posibil să se determine punctul de intrare al unei funcții cu o căutare text pe baza numelui funcției. Această operațiune este realizată de API GetProcAddress
care returnează adresa funcției al cărei nume este transmis ca parametru.
Se încarcă
Bibliotecile dinamice sunt încărcate de sistemul de operare în spațiul de memorie al procesului care le-a solicitat. În acest fel, accesarea codului DLL va avea o performanță aproape echivalentă cu cea a codului aplicației în sine sau a codului bibliotecilor statice (vom vedea de ce sunt aproape echivalente mai târziu).
Pentru a împiedica codul aplicației și codul DLL să ocupe aceeași locație de memorie, linkerul va trebui să pregătească DLL pentru relocare . În practică, sistemul de operare determină o zonă de memorie disponibilă și remapează orice referințe de memorie conținute în codul DLL. Deoarece acest lucru necesită timp, fiecare DLL are propria adresă de bază ideală: relocarea va fi necesară numai dacă o DLL anterioară a fost deja mapată la această adresă predeterminată. Pentru a specifica adresa ideală, puteți utiliza o regulă generală, bazată pe litera inițială a numelui DLL, conform tabelului următor:
Scrisoarea inițială | Adresa de bază |
---|---|
B.C | 0x60000000 |
DF | 0x61000000 |
GI | 0x62000000 |
JL | 0x63000000 |
MO | 0x64000000 |
relatii cu publicul | 0x65000000 |
PE | 0x66000000 |
VX | 0x67000000 |
YZ | 0x68000000 |
Link către un executabil
Conexiunea unui executabil la o bibliotecă dinamică are loc în timpul execuției (în timpul rulării ) și are loc prin intermediul LoadLibrary
API, care acceptă numele bibliotecii ca intrare . De exemplu, LoadLibrary(_T("MyLib.dll"))
va încărca DLL MyLib.dll
spațiul de memorie al aplicației.
Legătura poate fi de două tipuri: explicită sau implicită.
Link explicit
Conexiunea explicită este gestionată direct de codul programului cu ajutorul celor două API LoadLibrary
și GetProcAddress
descrise anterior. Dacă utilizați limbajul C , veți aloca un pointer funcției specificate în care, atunci când utilizați funcția solicitată, veți încărca adresa cu GetProcAddress
. Această tehnică vă permite să gestionați corect starea în care o DLL necesară nu este prezentă în sistem, dar, în general, este mai greoaie, deoarece necesită utilizarea explicită a celor două API-uri. Această tehnică este esențială atunci când se utilizează unele limbaje de programare, cum ar fi Visual Basic, de exemplu.
Link implicit
Legătura implicită este gestionată direct de linker la momentul compilării și este utilizată atunci când se presupune că o DLL este întotdeauna prezentă pe sistem. Ori de câte ori o funcție conținută într-un DLL este apelată în codul sursă, linkerul va lega apelul de funcție la o funcție stub , adică la o funcție fictivă. În interiorul executabilului va exista un tabel care conține butoanele pentru toate funcțiile DLL necesare. La încărcarea executabilului, sistemul de operare va încărca automat toate DLL-urile necesare și va mapa fiecare stub la punctul de intrare al funcției relative în DLL-ul relativ. Dacă nu este găsită o DLL necesară (sau chiar o singură funcție într-o DLL), sistemul de operare va bloca programul să înceapă cu un mesaj de eroare.
Utilizarea legăturii implicite are un dezavantaj în ceea ce privește performanța, deoarece de fiecare dată când este apelată o funcție conținută într-un DLL, există o dublă săritură pentru a funcționa: mai întâi către stub și apoi la adresa funcției; cheltuielile generale generate sunt de fapt neglijabile.
Conectarea implicită a fost întârziată
O variantă de legătură implicită așteptată de unii compilatori este legarea întârziată . În acest caz, se utilizează un stub special, care nu este mapat la încărcare de către sistemul de operare. În schimb, acest stub , prima dată când este invocat, se va mapa automat (cu tehnica de legătură explicită) la funcția DLL. Această tehnică are avantajul că nu necesită prezența DLL pentru a încărca executabilul, împreună cu comoditatea de a nu fi nevoie să încărcați în mod explicit biblioteca din cod.
Notă
Elemente conexe
linkuri externe
- Prezentare generală a DLL , pe negusweb.it .
- Creați un DLL în Visual Basic 2008 , la blackwolf96blog.wordpress.com .
- ( EN ) Ulrich Drepper, How to write shared libraries ( PDF ), pe people.redhat.com , 20 august 2006. Adus 1 iunie 2008 .