eftersom DLL är i huvudsak samma som EXEs, valet av vilka att producera som en del av länkprocessen är för tydlighet, eftersom det är möjligt att exportera funktioner och data från antingen.
det är inte möjligt att direkt utföra en DLL, eftersom det kräver en EXE för operativsystemet att ladda det via en ingångspunkt, därav förekomsten av verktyg som RUNDLL.EXE eller RUNDLL32.EXE som ger ingångspunkten och minimal ram för dll-filer som innehåller tillräckligt med funktionalitet för att utföra utan mycket stöd.,
dll-filer ger en mekanism för delad kod och data, vilket gör det möjligt för en utvecklare av delad kod / data att uppgradera funktionalitet utan att kräva att program länkas eller omkompileras. Ur applikationsutvecklingssynpunkt kan Windows och OS/2 ses som en samling av dll-filer som uppgraderas, vilket gör att applikationer för en version av operativsystemet kan fungera i en senare, förutsatt att OS-leverantören har säkerställt att gränssnitten och funktionaliteten är kompatibla.,
dll-filer körs i minnesutrymmet i samtalsprocessen och med samma åtkomstbehörigheter vilket innebär att det finns lite overhead i deras användning men också att det inte finns något skydd för den anropande EXE om DLL har någon form av bugg.
Memory managementEdit
i Windows API organiseras DLL-filerna i sektioner. Varje avsnitt har sin egen uppsättning attribut, som att vara skrivbar eller skrivskyddad, körbar (för kod) eller icke-körbar (för data) och så vidare.,
koden i en DLL delas vanligtvis bland alla processer som använder DLL; det vill säga de upptar en enda plats i fysiskt minne och tar inte upp utrymme i sidfilen. Windows använder inte positionsoberoende kod för sina dll-filer; istället genomgår koden omlokalisering när den laddas, fixar adresser för alla sina ingångspunkter på platser som är fria i minnesutrymmet i den första processen för att ladda DLL., I äldre versioner av Windows, där alla processer som körs upptog ett enda gemensamt adressutrymme, skulle en enda kopia av DLL-koden alltid vara tillräcklig för alla processer. Men i nyare versioner av Windows som använder separata adressutrymmen för varje program är det bara möjligt att använda samma omlokaliserade kopia av DLL i flera program om varje program har samma virtuella adresser gratis för att rymma DLL-koden., Om vissa program (eller deras kombination av redan laddade dll-filer) inte har dessa adresser gratis, måste en ytterligare fysisk kopia av DLL-koden skapas med hjälp av en annan uppsättning omlokaliserade inmatningspunkter. Om det fysiska minnet som upptas av en kodsektion ska återkrävas, kasseras innehållet och laddas senare direkt från DLL-filen efter behov.
i motsats till kodavsnitt är datasektionerna i en DLL vanligtvis privata; det vill säga varje process som använder DLL har sin egen kopia av alla DLL-data., Eventuellt kan datasektioner delas, vilket möjliggör interprocesskommunikation via detta delade minnesområde. Men eftersom användarrestriktioner inte gäller användningen av delat DLL-minne skapar detta ett säkerhetshål; nämligen kan en process korrumpera de delade uppgifterna, vilket sannolikt kommer att leda till att alla andra delningsprocesser uppträder oönskat. Till exempel kan en process som körs under ett gästkonto på detta sätt förstöra en annan process som körs under ett privilegierat konto. Detta är en viktig anledning att undvika användning av delade sektioner i DLL.,
om en DLL komprimeras av vissa körbara paket (t.ex. UPX) markeras alla dess kodsektioner som lästa och skriv, och kommer att vara oskadade. Läs-och skrivkodavsnitt, ungefär som privata dataavsnitt, är privata för varje process. DLLs med delade datasektioner bör således inte komprimeras om de är avsedda att användas samtidigt av flera program, eftersom varje programinstans skulle behöva bära sin egen kopia av DLL, vilket resulterar i ökad minnesförbrukning.
importera biblioteksedit
som statiska bibliotek, import bibliotek för dll-filer noteras av .,lib filändelsen. Till exempel kernel32.dll, det primära dynamiska biblioteket för Windows basfunktioner som filskapande och minneshantering, är länkat via kernel32.lib. Det vanliga sättet att berätta för ett importbibliotek från ett korrekt statiskt bibliotek är efter storlek: importbiblioteket är mycket mindre eftersom det bara innehåller symboler som hänvisar till den faktiska DLL, som ska behandlas vid länktid. Båda är ändå Unix ar format filer.
länkning till dynamiska bibliotek hanteras vanligtvis genom att länka till ett importbibliotek när man bygger eller länkar för att skapa en körbar fil., Den skapade körbara innehåller sedan en importadresstabell (IAT) genom vilken alla DLL-funktionsanrop refereras (varje refererad DLL-funktion innehåller sin egen post i IAT). Vid körning fylls IAT med lämpliga adresser som pekar direkt på en funktion i den separat laddade DLL.
i Cygwin / msys och MinGW ges importbiblioteken vanligtvis suffixet .dll.a
, som kombinerar både Windows DLL-suffixet och Unix ar-suffixet., Filformatet är liknande, men symbolerna som används för att markera importen är olika (_head_foo_dll vs __IMPORT_DESCRIPTOR_foo). Även om dess GNU Binutils toolchain kan generera importbibliotek och länka till dem, är det snabbare att länka till DLL direkt. En experimentella verktyg i MinGW kallas genlib kan användas för att generera importera libs med MSVC-stil symboler.
Symbolupplösning och bindingEdit
varje funktion som exporteras av en DLL identifieras av en numerisk ordinal och eventuellt ett namn. På samma sätt kan funktioner importeras från en DLL antingen genom ordinal eller med namn., Ordningsföljden representerar positionen för funktionens adresspekare i DLL-Exportadresstabellen. Det är vanligt att interna funktioner endast exporteras via ordinal. För de flesta Windows API-funktioner bevaras endast namnen över olika Windows-utgåvor; ordningsföljderna kan ändras. Således kan man inte på ett tillförlitligt sätt importera Windows API-funktioner av sina ordinaler.
importfunktioner genom ordinal ger bara något bättre prestanda än att importera dem med namn: export tabeller med DLL beställs med namn, så en binär sökning kan användas för att hitta en funktion., Indexet för det hittade namnet används sedan för att slå upp ordinalen i Export Ordinal tabellen. I 16-bitars fönster sorterades inte namntabellen, så namnet lookup overhead var mycket mer märkbart.
det är också möjligt att binda en körbar till en specifik version av en DLL, det vill säga att lösa adresserna för importerade funktioner vid kompilering. För bunden import sparar länken tidsstämpeln och kontrollsumman för DLL som importen är bunden till. Vid run-time kontrollerar Windows för att se om samma version av biblioteket används, och i så fall kringgår Windows bearbetning av importen., Annars, om biblioteket skiljer sig från den som var bunden till, Windows behandlar importen på ett normalt sätt.
bundna körbara filer laddas något snabbare om de körs i samma miljö som de sammanställdes för, och exakt samma gång om de körs i en annan miljö, så det finns ingen nackdel för att binda importen. Till exempel är alla vanliga Windows-program bundna till systemdll i deras respektive Windows-utgåva. Ett bra tillfälle att binda en ansökan import till sin målmiljö är under programmets installation., Detta håller biblioteken ”bundna” tills nästa OS-uppdatering. Det ändrar dock kontrollsumman för den körbara, så det är inte något som kan göras med signerade program eller program som hanteras av ett konfigurationshanteringsverktyg som använder kontrollsummor (till exempel MD5 kontrollsummor) för att hantera filversioner. Eftersom nyare Windows-versioner har flyttat från att ha fasta adresser för varje laddat bibliotek (av säkerhetsskäl), minskar möjligheten och värdet av att binda en körbar.,
Explicit run-time linkingEdit
DLL-filer kan uttryckligen laddas vid körning, en process som helt enkelt kallas run-time dynamisk länkning av Microsoft, genom att användaLoadLibrary
(ellerLoadLibraryEx
) API-funktionen. GetProcAddress
API-funktionen används för att slå upp exporterade symboler med namn och FreeLibrary
– för att lossa DLL-filen. Dessa funktioner är analoga med dlopen
, dlsym
och dlclose
I POSIX standard API.,
proceduren för explicit run-time-länkning är densamma på alla språk som stöder pekare till funktioner, eftersom det beror på Windows API snarare än språkkonstruktioner.
fördröjd loadingEdit
normalt startar ett program som är länkat mot ett DLL-importbibliotek om DLL inte kan hittas, eftersom Windows inte kör programmet om det inte kan hitta alla dll-filer som programmet kan behöva. Ett program kan dock länkas mot ett importbibliotek för att möjliggöra fördröjd laddning av det dynamiska biblioteket.,I det här fallet kommer operativsystemet inte att försöka hitta eller ladda DLL när programmet startar. istället ingår en stub i applikationen av länken som kommer att försöka hitta och ladda DLL genom LoadLibrary och GetProcAddress när en av dess funktioner kallas. Om DLL inte kan hittas eller laddas, eller den uppringda funktionen inte existerar, kommer programmet att generera ett undantag, som kan fångas och hanteras på lämpligt sätt. Om programmet inte hanterar undantaget kommer det att fångas av operativsystemet, vilket kommer att avsluta programmet med ett felmeddelande.,
fördröjningsladdningsmekanismen ger också anmälningskrokar, vilket gör att programmet kan utföra ytterligare bearbetning eller felhantering när DLL laddas och / eller någon DLL-funktion kallas.
Lämna ett svar