ponieważ biblioteki DLL są zasadniczo takie same jak Exe, wybór, który do wytworzenia jako część procesu łączenia jest dla jasności, ponieważ możliwe jest eksportowanie funkcji i danych z obu.
nie jest możliwe bezpośrednie uruchomienie biblioteki DLL, ponieważ wymaga ona EXE dla systemu operacyjnego, aby załadować ją przez punkt wejścia, stąd istnienie narzędzi takich jak RUNDLL.EXE lub RUNDLL32.EXE, które zapewniają punkt wejścia i minimalne ramy dla bibliotek DLL, które zawierają wystarczającą funkcjonalność do wykonania bez większego wsparcia.,
biblioteki DLL zapewniają mechanizm współdzielonego kodu i danych, umożliwiając programistom współdzielonego kodu / danych uaktualnianie funkcjonalności bez konieczności ponownego łączenia lub kompilowania aplikacji. Z punktu widzenia rozwoju aplikacji Windows i OS/2 mogą być traktowane jako zbiór bibliotek DLL, które są uaktualniane, umożliwiając aplikacje dla jednej wersji systemu operacyjnego do pracy w późniejszej, pod warunkiem, że dostawca systemu operacyjnego zapewnił, że interfejsy i funkcjonalność są kompatybilne.,
biblioteki DLL uruchamiają się w przestrzeni pamięci procesu wywołującego i z tymi samymi uprawnieniami dostępu, co oznacza, że jest mało narzutu w ich użyciu, ale także, że nie ma ochrony dla wywołującego EXE, jeśli DLL ma jakikolwiek błąd.
Zarządzanie Pamięciadytuj
w Windows API pliki DLL są podzielone na sekcje. Każda sekcja ma swój własny zestaw atrybutów, takich jak zapisywalny lub tylko do odczytu, wykonywalny (dla kodu) lub nie wykonywalny (dla danych), i tak dalej.,
kod biblioteki DLL jest zwykle współdzielony między wszystkimi procesami używającymi biblioteki DLL; to znaczy zajmują one jedno miejsce w pamięci fizycznej i nie zajmują miejsca w pliku strony. Windows nie używa kodu zależnego od pozycji dla swoich bibliotek DLL; zamiast tego Kod ulega relokacji podczas ładowania, ustalając adresy wszystkich punktów wejścia w miejscach, które są wolne w przestrzeni pamięci pierwszego procesu, który ładuje bibliotekę DLL., W starszych wersjach systemu Windows, w których wszystkie uruchomione procesy zajmowały jedną wspólną przestrzeń adresową, pojedyncza kopia kodu biblioteki DLL zawsze byłaby wystarczająca dla wszystkich procesów. Jednak w nowszych wersjach systemu Windows, które używają oddzielnych przestrzeni adresowych dla każdego programu, możliwe jest użycie tej samej przeniesionej kopii DLL w wielu programach, jeśli każdy program ma te same adresy wirtualne wolne, aby pomieścić kod DLL., Jeśli niektóre programy (lub ich kombinacja już załadowanych bibliotek DLL) nie mają tych adresów za darmo, należy utworzyć dodatkową fizyczną kopię kodu biblioteki DLL, używając innego zestawu przeniesionych punktów wejścia. Jeśli pamięć fizyczna zajmowana przez sekcję kodu ma zostać odzyskana, jej zawartość jest odrzucana, a następnie ponownie ładowana bezpośrednio z pliku DLL w razie potrzeby.
w przeciwieństwie do sekcji kodu, sekcje danych biblioteki DLL są zwykle prywatne; to znaczy, każdy proces korzystający z biblioteki DLL ma swoją własną kopię wszystkich danych biblioteki DLL., Opcjonalnie sekcje danych mogą być współdzielone, umożliwiając komunikację między procesami za pośrednictwem tego obszaru pamięci współdzielonej. Ponieważ jednak ograniczenia użytkownika nie dotyczą korzystania ze współdzielonej pamięci DLL, tworzy to lukę w zabezpieczeniach; mianowicie, jeden proces może uszkodzić udostępnione dane, co prawdopodobnie spowoduje, że wszystkie inne procesy udostępniania zachowają się niepożądanie. Na przykład proces działający na koncie gościa może w ten sposób uszkodzić inny proces działający na koncie uprzywilejowanym. Jest to ważny powód, aby uniknąć korzystania z udostępnionych sekcji w bibliotekach DLL.,
Jeśli biblioteka DLL jest kompresowana przez niektóre pakiety wykonywalne (np. UPX), wszystkie jej sekcje kodu są oznaczone jako odczyt i zapis i będą Nie udostępniane. Sekcje kodu do odczytu i zapisu, podobnie jak sekcje danych prywatnych, są prywatne dla każdego procesu. Dlatego biblioteki DLL ze współdzielonymi sekcjami danych nie powinny być kompresowane, jeśli mają być używane jednocześnie przez wiele programów, ponieważ każda instancja programu musiałaby posiadać własną kopię biblioteki DLL, co powodowałoby zwiększone zużycie pamięci.
Import bibliotekedytuj
podobnie jak biblioteki statyczne, biblioteki importu dla bibliotek DLL są odnotowywane przez .,rozszerzenie pliku lib. Na przykład kernel32.dll, podstawowa dynamiczna biblioteka dla podstawowych funkcji systemu Windows, takich jak tworzenie plików i zarządzanie pamięcią, jest połączona za pomocą jądra 32.lib. Standardowym sposobem odróżnienia biblioteki importu od odpowiedniej biblioteki statycznej jest rozmiar: biblioteka importu jest znacznie mniejsza, ponieważ zawiera tylko symbole odnoszące się do rzeczywistej biblioteki DLL, które mają być przetwarzane w czasie połączenia. Oba są plikami w formacie Unix ar.
łączenie z bibliotekami dynamicznymi jest zwykle obsługiwane przez łączenie z biblioteką importu podczas budowania lub łączenia w celu utworzenia pliku wykonywalnego., Utworzony plik wykonywalny zawiera tabelę adresów importu (iat), za pomocą której odwołuje się wszystkie wywołania funkcji DLL (każda odwołana funkcja DLL zawiera swój własny wpis w IAT). W czasie wykonywania IAT jest wypełniany odpowiednimi adresami, które kierują bezpośrednio do funkcji w oddzielnie załadowanej bibliotece DLL.
w Cygwin/MSYS i MinGW biblioteki importu mają standardowo przyrostek.dll.a
, łączący przyrostek DLL Windows i przyrostek AR Unix., Format pliku jest podobny, ale symbole używane do oznaczania importu są różne (_head_foo_dll vs __IMPORT_deskryptor_foo). Chociaż jego łańcuch narzędzi GNU Binutils może generować biblioteki importu i łączyć się z nimi, szybsze jest bezpośrednie połączenie z biblioteką DLL. Eksperymentalne narzędzie w MinGW o nazwie genlib może być używane do generowania bibliotek importowych z symbolami w stylu MSVC.
rozdzielczość i bindowanie Symboluedytuj
każda funkcja eksportowana przez bibliotekę DLL jest identyfikowana za pomocą kolejności liczbowej i opcjonalnie nazwy. Podobnie, funkcje mogą być importowane z biblioteki DLL albo porządkowo, albo z nazwy., Kolejność przedstawia pozycję wskaźnika adresu funkcji w tabeli adresów eksportu DLL. Często funkcje wewnętrzne są eksportowane tylko za pomocą porządków. W przypadku większości funkcji Windows API tylko nazwy są zachowywane w różnych wydaniach Windows; kolejność może ulec zmianie. W związku z tym nie można niezawodnie importować funkcji Windows API według ich porządków.
Importowanie funkcji według kolejności zapewnia tylko nieco lepszą wydajność niż importowanie ich po nazwie: tabele eksportu bibliotek DLL są uporządkowane według nazwy, więc wyszukiwanie binarne może być użyte do znalezienia funkcji., Indeks znalezionej nazwy jest następnie używany do wyszukiwania kolejności w tabeli Porządkowej eksportu. W 16-bitowych oknach tabela nazw nie była sortowana, więc lista nazw była znacznie bardziej zauważalna.
możliwe jest również Związanie pliku wykonywalnego z określoną wersją biblioteki DLL, czyli rozwiązanie adresów zaimportowanych funkcji w czasie kompilacji. Dla powiązanych importów linker zapisuje znacznik czasu i sumę kontrolną biblioteki DLL, do której Import jest związany. W czasie wykonywania Windows sprawdza, czy używana jest ta sama wersja biblioteki, a jeśli tak, Windows omija przetwarzanie importu., W przeciwnym razie, jeśli Biblioteka jest inna niż ta, z którą była powiązana, Windows przetwarza import w normalny sposób.
powiązane pliki wykonywalne ładują się nieco szybciej, jeśli są uruchamiane w tym samym środowisku, dla którego zostały skompilowane, i dokładnie w tym samym czasie, jeśli są uruchamiane w innym środowisku, więc nie ma wad wiązania importu. Na przykład wszystkie standardowe aplikacje systemu Windows są powiązane z bibliotekami DLL systemu w ich odpowiednim wydaniu systemu Windows. Dobrą okazją do powiązania importu aplikacji z jej docelowym środowiskiem jest instalacja aplikacji., Dzięki temu biblioteki są „związane” aż do następnej aktualizacji systemu operacyjnego. Zmienia to jednak sumę kontrolną pliku wykonywalnego, więc nie jest to coś, co można zrobić z podpisanymi programami lub programami zarządzanymi przez narzędzie do zarządzania konfiguracją, które używa sum kontrolnych (takich jak sumy kontrolne MD5) do zarządzania wersjami plików. Ponieważ nowsze wersje systemu Windows odeszły od posiadania stałych adresów dla każdej załadowanej biblioteki( ze względów bezpieczeństwa), możliwość i wartość wiązania pliku wykonywalnego maleje.,
jawne łączenie w czasie uruchomieniaedytuj
pliki DLL mogą być jawnie ładowane w czasie uruchamiania, proces określany po prostu jako dynamiczne łączenie w czasie uruchamiania przez Microsoft, za pomocą funkcji APILoadLibrary
(lubLoadLibraryEx
). Funkcja API GetProcAddress
służy do wyszukiwania eksportowanych symboli według nazw, a FreeLibrary
– do rozładowywania biblioteki DLL. Funkcje te są analogiczne do dlopen
, dlsym
oraz dlclose
w standardowym API POSIX.,
procedura jawnego łączenia w czasie wykonywania jest taka sama w każdym języku, który obsługuje wskaźniki do funkcji, ponieważ zależy od interfejsu API systemu Windows, a nie od konstrukcji językowych.
opóźnione ładowanieedit
normalnie, aplikacja, która jest połączona z biblioteką importu DLL nie uruchomi się, jeśli DLL nie można znaleźć, ponieważ system Windows nie uruchomi aplikacji, chyba że może znaleźć wszystkie biblioteki DLL, które aplikacja może potrzebować. Jednak aplikacja może być powiązana z biblioteką importu, aby umożliwić opóźnione ładowanie biblioteki dynamicznej.,W tym przypadku system operacyjny nie będzie próbował znaleźć lub załadować DLL podczas uruchamiania aplikacji; zamiast tego, stub jest zawarty w aplikacji przez linker, który będzie próbował znaleźć i załadować DLL poprzez LoadLibrary i GetProcAddress, gdy jedna z jego funkcji jest wywołana. Jeśli biblioteki DLL nie można znaleźć lub załadować, lub wywołana funkcja nie istnieje, aplikacja wygeneruje wyjątek, który może być odpowiednio przechwycony i obsługiwany. Jeśli aplikacja nie obsługuje wyjątku, zostanie on przechwycony przez system operacyjny, który zakończy program z Komunikatem o błędzie.,
mechanizm opóźnionego ładowania zapewnia również haki powiadomień, umożliwiając aplikacji wykonanie dodatkowego przetwarzania lub obsługi błędów podczas ładowania biblioteki DLL i / lub wywoływania dowolnej funkcji DLL.
Dodaj komentarz