Co to jest biblioteka DLL?

Dotyczy: Brak

Podsumowanie


W tym artykule opisano, co to jest biblioteka łączona dynamicznie (DLL), i różne problemy, które mogą wystąpić podczas korzystania z bibliotek DLL.

Następnie w tym artykule opisano niektóre zaawansowane problemy, które należy wziąć pod uwagę podczas opracowywania własnych bibliotek DLL. W tym artykule opisano metody dynamicznego łączenia, zależności DLL, punkty wejścia DLL, eksportowanie funkcji DLL i narzędzia do rozwiązywania problemów DLL.

Ten artykuł kończy się porównaniem bibliotek DLL wysokiego poziomu z zestawami Microsoft .NET Framework.

WPROWADZENIE


W systemach operacyjnych Microsoft Windows, które są wymienione w sekcji „Dotyczy”, wiele funkcji systemu operacyjnego jest dostarczanych przez biblioteki łączone dynamicznie (DLL). Ponadto po uruchomieniu programu na jednym z tych systemów operacyjnych Windows wiele funkcji programu może być dostarczanych przez biblioteki DLL. Na przykład niektóre programy mogą zawierać wiele różnych modułów, a każdy moduł programu jest zawarty i rozpowszechniany w bibliotekach DLL.

Korzystanie z bibliotek DLL pomaga promować modularyzację kodu, ponowne użycie kodu, efektywne wykorzystanie pamięci i zmniejszenie miejsca na dysku. W związku z tym system operacyjny i programy mogą ładować się szybciej, działać szybciej i zajmować mniej miejsca na dysku na komputerze.

Gdy program używa biblioteki DLL, problem zależności może spowodować, że program nie uruchomi się. Gdy program używa biblioteki DLL, powstaje zależność. Jeśli inny program zastępuje i przerywa tę zależność, oryginalny program może nie zostać pomyślnie uruchomiony.

Wraz z wprowadzeniem Microsoft .NET Framework, większość problemów zależności zostały wyeliminowane za pomocą zestawów.

Więcej informacji


Co to jest biblioteka DLL?

Biblioteka DLL jest biblioteką zawierającą kod i dane, które mogą być używane przez więcej niż jeden program w tym samym czasie. Na przykład w systemach operacyjnych Windows, plik comdlg32 DLL wykonuje typowe funkcje związane z oknami dialogowymi. W związku z tym każdy program może użyć funkcji, która jest zawarta w tej bibliotece DLL do zaimplementowania okna dialogowego Otwórz. Pomaga to promować ponowne użycie kodu i efektywne wykorzystanie pamięci.

Za pomocą biblioteki DLL, program może być zmodularyzowany na oddzielne składniki. Na przykład program księgowy może być sprzedawany przez moduł. Każdy moduł można załadować do głównego programu w czasie wykonywania, jeśli ten moduł jest zainstalowany. Ponieważ moduły są oddzielne, czas ładowania programu jest szybszy, a moduł jest ładowany tylko wtedy, gdy wymagana jest ta funkcjonalność.

Ponadto aktualizacje są łatwiejsze do zastosowania do każdego modułu bez wpływu na inne części programu. Na przykład może to być program listy płac, a stawki podatku zmieniają się każdego roku. Gdy te zmiany są izolowane do biblioteki DLL, można zastosować aktualizację bez konieczności tworzenia lub zainstalować cały program ponownie.

Na poniższej liście opisano niektóre pliki, które są implementowane jako biblioteki DLL w systemach operacyjnych Windows:
  • Pliki formantów ActiveX (.ocx)
    Przykładem formantu ActiveX jest formant kalendarza, który pozwala wybrać datę z kalendarza.
  • Pliki w Panelu sterowania (.cpl)
    Przykładem pliku .cpl jest element, który znajduje się w Panelu sterowania. Każdy element jest wyspecjalizowaną biblioteką DLL.
  • Pliki sterownika urządzenia (.drv)
    Przykładem sterownika urządzenia jest sterownik drukarki, który steruje drukowaniem na drukarce.

DLL - zalety

Na poniższej liście opisano niektóre zalety, które są zapewnione, gdy program używa biblioteki DLL:
  • Mniejsze użycie zasobów
    Gdy wiele programów korzysta z tej samej biblioteki funkcji, biblioteka DLL może zmniejszyć duplikowanie kodu, który jest ładowany na dysku i w pamięci fizycznej. Może to znacznie wpłynąć na wydajność nie tylko programu, który jest uruchomiony na pierwszym planie, ale także inne programy, które są uruchomione w systemie operacyjnym Windows.
  • Promuje modułową architekturę
    Biblioteka DLL pomaga promować opracowywanie programów modułowych. Pomaga to rozwijać duże programy, które wymagają wielu wersji językowych lub program, który wymaga architektury modułowej. Przykładem programu modułowego jest program księgowości, posiadający wiele modułów, które mogą być ładowane dynamicznie w czasie wykonywania.
  • Ułatwia wdrażanie i instalację
    Gdy funkcja w bibliotece DLL wymaga aktualizacji lub poprawki, wdrażanie i instalacja biblioteki DLL nie wymaga ponownego połączenia programu z biblioteką DLL. Ponadto jeśli wiele programów korzysta z tej samej biblioteki DLL, programy te skorzystają z aktualizacji lub poprawki. Ten problem może występować częściej podczas korzystania z biblioteki DLL innej firmy, która jest regularnie aktualizowana lub ustalona.

Zależności bibliotek DLL

Gdy program lub biblioteka DLL używa funkcji DLL w innej bibliotece DLL, powstaje zależność. W związku z tym program nie będzie już samowystarczalny i może doświadczyć problemów, jeśli zależność zostanie przerwana. Na przykład program może nie działać, jeśli wystąpi jedna z następujących czynności:
  • Zależna biblioteka DLL jest uaktualniana do nowej wersji.
  • Zależna biblioteka DLL jest ustalona.
  • Zależna biblioteka DLL jest zastępowana wcześniejszą wersją.
  • Zależna biblioteka DLL jest usuwana z komputera.
Te działania są zazwyczaj nazywane konfliktami DLL. Jeśli zgodność z poprzednimi wersjami nie jest wymuszana, program może nie zostać pomyślnie uruchomiony.

Poniższa lista zawiera opis zmian wprowadzonych w systemie Microsoft Windows 2000 i nowszych systemach operacyjnych Windows w celu zminimalizowania problemów z zależnościami:
  • Ochrona plików systemu Windows
    W ochronie plików systemu Windows system operacyjny uniemożliwia aktualizację lub usunięcie przez nieautoryzowanego użytkownika bibliotek DLL systemu. W związku z tym gdy instalacja programu próbuje usunąć lub zaktualizować bibliotekę DLL, która jest zdefiniowana jako systemowa biblioteka DLL, Ochrona plików systemu Windows będzie szukała prawidłowego podpisu cyfrowy.
  • Prywatne biblioteki DLL
    Prywatne biblioteki DLL umożliwiają wyodrębnienie programu ze zmian wprowadzonych w udostępnionych bibliotekach DLL. Prywatne biblioteki DLL używają informacji specyficznych dla wersji lub pustego pliku .local w celu wymuszenia wersji biblioteki DLL używanej przez program. Aby korzystać z prywatnych bibliotek DLL, zlokalizuj biblioteki DLL w folderze głównym programu. Następnie w przypadku nowych programów należy dodać informacje specyficzne dla wersji do biblioteki DLL. W przypadku starych programów należy użyć pustego pliku .local. Każda metoda informuje system operacyjny, aby używać prywatnych bibliotek DLL, które znajdują się w folderze głównym programu.

Narzędzia do rozwiązywania problemów z biblioteką DLL

Dostępne są różne narzędzia ułatwiające rozwiązywanie problemów z biblioteką DLL. Oto niektóre z dostępnych narzędzi.

Zależność Walker

Narzędzie zależności Walker umożliwia rekursywne skanowania dla wszystkich zależnych bibliotek DLL, które są używane przez program. Po otwarciu programu badania zależności Walker wykonuje on następujące kontrole:
  • Program Walker sprawdza brakujące biblioteki DLL.
  • Program Walker sprawdza pliki programów lub bibliotek DLL, które nie są prawidłowe.
  • Program Walker sprawdza, czy funkcje importowania i eksportowania odpowiadają.
  • Program Walker sprawdza cykliczne błędy zależności.
  • Program Walker sprawdza moduły, które nie są prawidłowe, ponieważ moduły te są przeznaczone dla innego systemu operacyjnego.
Za pomocą programu Walker, można dokumentować wszystkie biblioteki DLL, które używa program. Może to pomóc w zapobieganiu i korygowaniu problemów DLL, które mogą wystąpić w przyszłości. Program Walker znajduje się w następującym katalogu podczas instalowania programu Microsoft Visual Studio 6.0:
dysk\Program Files\Microsoft Visual Studio\Common\Tools

DLL Universal Problem Solver

Narzędzie DLL Universal problem solver (DUPS) służy do inspekcji, porównywania, dokumentowania i wyświetlania informacji o bibliotece DLL. Poniższa lista zawiera opis narzędzi, które tworzą narzędzie DUPS:
  • Dlister.exe
    To narzędzie wylicza wszystkie biblioteki DLL na komputerze i rejestruje informacje w pliku tekstowym lub pliku bazy danych.
  • Dcomp.exe
    To narzędzie porównuje biblioteki DLL, które są wymienione w dwóch plikach tekstowych i tworzy trzeci plik tekstowy, który zawiera różnice.
  • Dtxt2DB.exe
    To narzędzie ładuje pliki tekstowe, które są tworzone przy użyciu narzędzia Dlister.exe i narzędzia Dcomp.exe do bazy danych dllHell.
  • DlgDtxt2DB.exe
    To narzędzie udostępnia graficzną wersję interfejsu użytkownika (GUI) narzędzia Dtxt2DB.exe.
Aby uzyskać więcej informacji na temat narzędzia DUPS, kliknij następujący numer artykułu w celu wyświetlenia tego artykułu z bazy wiedzy Microsoft Knowledge Base:
247957 Używanie DUPS.exe w celu rozwiązania problemów ze zgodnością DLL
 

Baza danych pomocy DLL

Baza danych pomocy biblioteki DLL pomaga zlokalizować określone wersje bibliotek DLL, które są instalowane przez produkty oprogramowania firmy Microsoft. 

Tworzenie bibliotek DLL

W tej sekcji opisano problemy i wymagania, które należy wziąć pod uwagę podczas opracowywania własnych bibliotek DLL.

Typy bibliotek DLL

Podczas ładowania biblioteki DLL w aplikacji, dwie metody łączenia umożliwiają wywoływanie wyeksportowanych funkcji DLL. Dwie metody łączenia to dynamiczne łączenie w czasie wczytywania i dynamiczne łączenie w czasie wykonywania.
Dynamiczne łączenie w czasie wczytywania
W czasie ładowania dynamiczne łączenie aplikacji sprawia, że jawne wywołania do wyeksportowanych funkcji DLL, takich jak funkcje lokalne. Aby użyć dynamicznego łączenia w czasie ładowania, należy podać plik nagłówka (.h) i plik biblioteki (.lib) importu podczas kompilowania i łączenia aplikacji. Po wykonaniu tej czynności konsolidator zapewni systemowi informacje, które są wymagane do załadowania biblioteki DLL i rozwiązania wyeksportowanych lokalizacji funkcji DLL w czasie ładowania.
Dynamiczne łączenie w czasie wykonywania
W czasie wykonywania dynamicznego łączenia, aplikacja wywołuje albo funkcję LoadLibrary, albo LoadLibraryEx, aby załadować biblioteki DLL w czasie wykonywania. Po pomyślnym załadowaniu biblioteki DLL, należy użyć funkcji GetProcAddress, aby uzyskać adres wyeksportowanej funkcji DLL, którą chcesz przywołać. Korzystając z dynamicznego łączenia w czasie wykonywania, nie jest potrzebny plik biblioteki importu.

Poniższa lista zawiera opis kryteriów aplikacji, kiedy należy używać dynamicznego łączenia w czasie ładowania i dynamicznego łączenia w czasie wykonywania:
  • Wydajność uruchamiania
    Jeśli początkowa wydajność uruchamiania aplikacji jest ważna, należy użyć dynamicznego łączenia w czasie wykonywania.
  • Łatwość obsługi
    W trakcie dynamiczne łączenie w czasie ładowania, wyeksportowane funkcje DLL są traktowane jak funkcje lokalne. Dzięki temu można łatwo wywołać te funkcje.
  • Logika aplikacji
    W trakcie dynamiczne łączenie w czasie wykonywania aplikacja może rozgałęzić się, aby załadować różne moduły zgodnie z wymaganiami. Jest to ważne podczas opracowywania wersji wielojęzycznych.

Punkt wejścia biblioteki DLL

Podczas tworzenia biblioteki DLL, można opcjonalnie określić funkcję punktu wejścia. Funkcja punktu wejścia jest wywoływana, gdy procesy lub wątki dołączają się lub odłączają od biblioteki DLL. Można użyć funkcji punktu wejścia, aby zainicjować struktury danych lub zniszczyć struktury danych zgodnie z wymaganiami biblioteki DLL. Ponadto jeśli aplikacja jest wielowątkowa, można użyć lokalnego magazynu wątków (TLS) do przydzielenia pamięci, który jest prywatny dla każdego wątku w funkcji punktu wejścia. Poniższy kod jest przykładem funkcji punktu wejścia DLL.
BOOL APIENTRY DllMain(HANDLE hModule,// Handle to DLL moduleDWORD ul_reason_for_call,// Reason for calling functionLPVOID lpReserved ) // Reserved{switch ( ul_reason_for_call ){case DLL_PROCESS_ATTACHED:// A process is loading the DLL.break;case DLL_THREAD_ATTACHED:// A process is creating a new thread.break;case DLL_THREAD_DETACH:// A thread exits normally.break;case DLL_PROCESS_DETACH:// A process unloads the DLL.break;}return TRUE;}
Gdy funkcja punktu wejścia zwraca wartość FAŁSZ, aplikacja nie uruchomi się, jeśli używasz dynamicznego łączenia w czasie ładowania. Jeśli używasz dynamicznego łączenia w czasie wykonywania, tylko poszczególne biblioteki DLL nie zostaną załadowane.

Funkcja punktu wejścia powinna wykonywać tylko proste zadania inicjowania i nie należy wywoływać innych funkcji ładowania lub kończenia biblioteki DLL. Na przykład w funkcji punktu wejścia, nie należy bezpośrednio lub pośrednio wywoływać funkcji LoadLibrary lub LoadLibraryEx. Ponadto nie należy wywoływać funkcji FreeLibrary, gdy proces jest zakańczany.

Uwaga W aplikacjach wielowątkowych upewnij się, że dostęp do danych globalnych DLL jest zsynchronizowany (bezpieczne dla wątków), aby uniknąć uszkodzenia danych. Aby to zrobić, użyj protokołu TLS do dostarczania unikatowych danych dla każdego wątku.

Eksportowanie funkcji DLL

Aby wyeksportować funkcje DLL, można dodać słowo kluczowe funkcji do wyeksportowanych funkcji DLL lub utworzyć plik definicji (.def) modułu, który zawiera listę wyeksportowanych funkcji DLL.

Aby użyć słowa kluczowego funkcji, należy zadeklarować każdą funkcję, którą chcesz wyeksportować, za pomocą następującego słowa kluczowego:
__declspec(dllexport)
Aby użyć wyeksportowanych funkcji DLL w aplikacji, należy zadeklarować każdą funkcję, którą chcesz zaimportować, za pomocą następującego słowa kluczowego:
__declspec(dllimport)
Zazwyczaj należy użyć jednego pliku nagłówkowego, który ma instrukcję define i ifdef do oddzielenia instrukcji eksport i import.

Można również użyć pliku definicji modułu do deklarowania wyeksportowanych funkcji DLL. Korzystając z pliku definicji modułu, nie trzeba dodawać słowa kluczowego funkcji do wyeksportowanych funkcji DLL. W pliku definicji modułu, należy zadeklarować instrukcję Library i EXPORTS dla biblioteki DLL. Poniższy kod jest przykładem pliku definicji.
// SampleDLL.def//LIBRARY "sampleDLL"EXPORTS  HelloWorld

Przykładowa Biblioteka DLL i aplikacja

W Microsoft Visual C++ 6.0 można utworzyć bibliotekę DLL, wybierając albo typ projektu Win32 biblioteki dołączanej dynamicznie, albo
MFC AppWizard (dll).

Poniższy kod jest przykładem biblioteki DLL, który został utworzony w programie Visual C++ przy użyciu
projektu typu Biblioteki dołączanej dynamicznie Win32.
// SampleDLL.cpp//#include "stdafx.h"#define EXPORTING_DLL#include "sampleDLL.h"BOOL APIENTRY DllMain( HANDLE hModule,                        DWORD  ul_reason_for_call,                        LPVOID lpReserved ){    return TRUE;}void HelloWorld(){MessageBox( NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);}
// File: SampleDLL.h//#ifndef INDLL_H#define INDLL_H#ifdef EXPORTING_DLLextern __declspec(dllexport) void HelloWorld() ;#elseextern __declspec(dllimport) void HelloWorld() ;#endif#endif
Poniższy kod jest przykładem projektu aplikacji Win32, która wywołuje wyeksportowaną funkcję DLL w bibliotece SampleDLL DLL.
// SampleApp.cpp //#include "stdafx.h"#include "sampleDLL.h"int APIENTRY WinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){ HelloWorld();return 0;}
UwagaW trakcie dynamicznego łączenia w czasie ładowania należy połączyć bibliotekę importu SampleDLL.lib, która jest tworzony podczas tworzenia projektu SampleDLL.

W trakcie dynamicznego łączenia w czasie wykonywania, użyj kodu, który jest podobny do następującego kodu do wywoływania SampleDLL.dll wyeksportowanej funkcji DLL.
...typedef VOID (*DLLPROC) (LPTSTR);...HINSTANCE hinstDLL;DLLPROC HelloWorld;BOOL fFreeDLL;hinstDLL = LoadLibrary("sampleDLL.dll");if (hinstDLL != NULL){    HelloWorld = (DLLPROC) GetProcAddress(hinstDLL, "HelloWorld");    if (HelloWorld != NULL)        (HelloWorld);    fFreeDLL = FreeLibrary(hinstDLL);}...
Podczas kompilowania i łączenia aplikacji SampleDLL, system operacyjny Windows wyszukuje SampleDLL DLL w następujących lokalizacjach w następującej kolejności:
  1. Folder aplikacji
  2. Bieżący folder
  3. Folder systemu Windows

    Uwaga Funkcja GetSystemDirectory zwraca ścieżkę folderu systemu Windows.
  4. Folder systemu Windows

    Uwaga Funkcja GetWindowsDirectory zwraca ścieżkę folderu systemu Windows.

Środowisko .NET Framework

Wraz z wprowadzeniem Microsoft .NET i .NET Framework, większość problemów, które są skojarzone z bibliotekami DLL zostały wyeliminowane za pomocą zestawów. Zestaw jest jednostką logiczną funkcji, która jest uruchamiana pod kontrolą .NET Common language runtime (CLR). Zestaw fizycznie istnieje jako plik .dll lub jako plik .exe. Jednak wewnętrznie zestaw bardzo różni się od Microsoft Win32 DLL.

Plik zestawu zawiera manifest zestawu, metadane typu, kod języka pośredniego (MSIL) firmy Microsoft i inne zasoby. Manifest zestawu zawiera metadane zestawu, który zaś zawiera wszystkie informacje, które są wymagane do tego, aby zestaw samodzielnie się opisywał. Następujące informacje są zawarte w manifeście zestawu:
  • Nazwa zestawu
  • Wersja
  • Informacje o kulturze
  • Informacje o silnej nazwie
  • Lista zestawów plików
  • Informacje referencyjne o typie
  • Informacje o zestawie odniesienia i zależności
Nie można bezpośrednio wykonać kodu MSIL, który jest zawarty w zestawie. Zamiast tego wykonanie kodu MSIL jest zarządzane za pośrednictwem środowiska CLR. Domyślnie podczas tworzenia zestawu, zestaw jest prywatny dla aplikacji. Utworzenie zestawu udostępnionego wymaga przypisania silnej nazwy do zestawu, a następnie opublikowania wirtualnego pliku dziennika w globalnej pamięci podręcznej zestawów.

Poniższa lista zawiera opis niektórych funkcji zestawów w porównaniu do funkcji bibliotek DLL systemu Win32:
  • Samodzielne opisywanie
    Podczas tworzenia zestawu, wszystkie informacje, które są wymagane dla środowiska CLR do uruchomienia zestawu są zawarte w manifeście zestawu. Manifest zestawu zawiera listę zestawów zależnych. W związku z tym CLR może zachować spójny zbiór zestawów, które są używane w aplikacji. W bibliotekach DLL systemu Win32 nie można zachować spójności między zestawami bibliotek DLL, które są używane w aplikacji, korzystając z udostępnionych bibliotek DLL.
  • Wersjonowanie
    W manifeście zestawu informacje o wersji są rejestrowane i wymuszane przez środowisko CLR. Ponadto zasady wersji umożliwiają wymuszenie użycia specyficzne dla wersji. W bibliotekach DLL systemu Win32 przechowywanie wersji nie może być wymuszane przez system operacyjny. Zamiast tego należy się upewnić, że biblioteki DLL są zgodne z poprzednimi wersjami.
  • Instalacje w trybie równoległym
    Zestawy obsługują wdrażanie w trybie równoległym. Jedna aplikacja może używać jednej wersji zestawu, a inna aplikacja może używać innej wersji zestawu. Począwszy od systemu Windows 2000, wdrażania w trybie równoległym są obsługiwane przez lokalizowanie bibliotek DLL w folderze aplikacji. Ponadto Ochrona plików systemu Windows zapobiega nadpisaniu lub zastąpieniu przez nieautoryzowanego użytkownika bibliotek DLL systemu.
  • Samodzielne oddzielenie i izolacja
    Aplikacja opracowana przy użyciu zestawu może być niezależna i odizolowana od innych aplikacji uruchomionych na komputerze. Ta funkcja pomaga w tworzeniu instalacji o zerowym wpływie na środowisko pracy.
  • Wykonanie
    Zestaw jest uruchamiany w ramach uprawnień zabezpieczeń, które są dostarczane w manifeście zestawu i które są kontrolowane przez środowisko CLR.
  • Niezależny od języka
    Zestaw można opracować przy użyciu jednego z obsługiwanych języków .NET. Na przykład można opracować zestaw w programie Microsoft Visual C#, a następnie użyć zestawu w projekcie programu Microsoft Visual Basic .NET.