Dynamiczny linker

W informatyce dynamiczny linker to część systemu operacyjnego , która ładuje i łączy biblioteki współdzielone potrzebne do pliku wykonywalnego , gdy jest on wykonywany (w „ czasie wykonywania ”), kopiując zawartość bibliotek z pamięci trwałej do pamięci RAM , wypełniając skok tabele i przenoszenie wskaźników . Konkretny system operacyjny i format pliku wykonywalnego określają sposób działania dynamicznego linkera i sposób jego implementacji.

Łączenie jest często określane jako proces wykonywany podczas kompilacji pliku wykonywalnego , podczas gdy dynamiczny linker to specjalna część systemu operacyjnego, która ładuje zewnętrzne biblioteki współdzielone do uruchomionego procesu , a następnie dynamicznie wiąże te biblioteki współdzielone z uruchomionym procesem. Takie podejście jest również nazywane dynamicznym łączeniem lub późnym łączeniem .

Implementacje

Microsoft Windows

Biblioteka dołączana dynamicznie lub DLL to implementacja koncepcji biblioteki udostępnionej przez firmę Microsoft w systemach operacyjnych Microsoft Windows i OS/2 . Biblioteki te mają zwykle rozszerzenie pliku DLL , OCX (dla bibliotek zawierających formanty ActiveX ) lub DRV (dla starszych sterowników systemowych ). Formaty plików dla bibliotek DLL są takie same jak dla plików Windows EXE — to znaczy Portable Executable (PE) dla 32-bitowego i 64-bitowego systemu Windows oraz New Executable (NE) dla 16-bitowego systemu Windows. Podobnie jak w przypadku plików EXE, biblioteki DLL mogą zawierać kod , dane i zasoby w dowolnej kombinacji.

Pliki danych o tym samym formacie pliku co biblioteka DLL, ale z różnymi rozszerzeniami plików i prawdopodobnie zawierające tylko sekcje zasobów, można nazwać bibliotekami DLL zasobów. Przykładami takich bibliotek DLL są wielojęzyczne biblioteki interfejsu użytkownika z rozszerzeniem MUI , biblioteki ikon , czasami mające rozszerzenie ICL , oraz pliki czcionek , mające rozszerzenia FON i FOT .

Systemy uniksopodobne wykorzystujące ELF i systemy oparte na Darwin

W większości systemów uniksopodobnych większość kodu maszynowego tworzącego dynamiczny linker jest w rzeczywistości zewnętrznym plikiem wykonywalnym, który jądro systemu operacyjnego ładuje i wykonuje jako pierwsze w nowo utworzonej przestrzeni adresowej procesu w wyniku wywołania funkcji exec lub posix_spawn . W czasie łączenia ścieżka dynamicznego linkera, który powinien być użyty, jest osadzona w wykonywalnym obrazie.

Kiedy ładowany jest plik wykonywalny, jądro systemu operacyjnego odczytuje z niego ścieżkę do dynamicznego linkera, a następnie próbuje załadować i wykonać ten inny wykonywalny plik binarny; jeśli ta próba się nie powiedzie, ponieważ na przykład nie ma pliku o tej ścieżce, próba wykonania oryginalnego pliku wykonywalnego kończy się niepowodzeniem. Następnie dynamiczny linker ładuje początkowy obraz wykonywalny i wszystkie dynamicznie połączone biblioteki, od których jest zależny, i uruchamia plik wykonywalny. binarnego interfejsu aplikacji systemu operacyjnego .

Systemy wykorzystujące ELF

W systemach typu Unix, które używają ELF do obrazów wykonywalnych i bibliotek dynamicznych, takich jak Solaris , 64-bitowe wersje HP-UX , Linux , FreeBSD , NetBSD , OpenBSD i DragonFly BSD , ścieżka dynamicznego linkera, który powinien być używany jest osadzony w czasie łącza w sekcji .interp segmentu PT_INTERP pliku wykonywalnego . W tych systemach dynamicznie ładowane biblioteki współdzielone można rozpoznać po przyrostku nazwy pliku .so (obiekt współdzielony).

Można wpłynąć na dynamiczny linker, aby zmodyfikował swoje zachowanie podczas wykonywania programu lub łączenia programu, a przykłady tego można zobaczyć na stronach podręcznika konsolidatora w czasie wykonywania dla różnych systemów uniksopodobnych. Typową modyfikacją tego zachowania jest użycie zmiennych środowiskowych LD_LIBRARY_PATH i LD_PRELOAD , które dostosowują proces łączenia w czasie wykonywania, odpowiednio wyszukując biblioteki współużytkowane w alternatywnych lokalizacjach oraz wymuszając ładowanie i łączenie bibliotek, które w innym przypadku by nie istniały. Przykładem jest zlibc, znany również jako uncompress.so , który ułatwia przezroczystą dekompresję, gdy jest używany przez hack LD_PRELOAD ; w konsekwencji możliwe jest odczytywanie wstępnie skompresowanych (skompresowanych gzipem) danych plików w systemach BSD i Linux tak, jakby pliki nie były skompresowane, zasadniczo umożliwiając użytkownikowi dodanie przezroczystej kompresji do bazowego systemu plików, chociaż z pewnymi zastrzeżeniami. Mechanizm jest elastyczny, pozwalając na trywialne dostosowanie tego samego kodu do dodatkowego lub alternatywnego przetwarzania danych podczas odczytu pliku, przed dostarczeniem tych danych żądającemu procesowi użytkownika.

macOS i iOS

W systemie operacyjnym Apple Darwin oraz w zbudowanych na nim systemach operacyjnych macOS i iOS ścieżka dynamicznego linkera, który powinien być używany, jest osadzona w czasie łączenia w jednym z poleceń ładowania Mach-O w obrazie wykonywalnym. W tych systemach dynamicznie ładowane biblioteki współdzielone można rozpoznać po przyrostku nazwy pliku .dylib lub po umieszczeniu ich w pakiecie dla struktury.

Dynamiczny linker nie tylko łączy docelowy plik wykonywalny z bibliotekami współdzielonymi, ale także umieszcza funkcje kodu maszynowego w określonych punktach adresowych w pamięci, o których docelowy plik wykonywalny wie w czasie łączenia. Kiedy plik wykonywalny chce wejść w interakcję z dynamicznym linkerem, po prostu wykonuje specyficzne dla maszyny wywołanie lub instrukcję skoku do jednego z tych dobrze znanych punktów adresowych. Pliki wykonywalne na platformach macOS i iOS często wchodzą w interakcję z dynamicznym linkerem podczas wykonywania procesu; wiadomo nawet, że plik wykonywalny może wchodzić w interakcję z dynamicznym linkerem, powodując ładowanie większej liczby bibliotek i rozpoznawanie większej liczby symboli w kilka godzin po pierwszym uruchomieniu. Powodem, dla którego program macOS lub iOS tak często wchodzi w interakcję z dynamicznym linkerem, są zarówno interfejsy API Cocoa i Cocoa Touch firmy Apple , jak i język Objective-C , w którym są one implementowane (więcej informacji można znaleźć w ich głównych artykułach).

Dynamiczny linker można zmusić do zmodyfikowania niektórych jego zachowań; jednak w przeciwieństwie do innych systemów operacyjnych typu Unix, te modyfikacje są wskazówkami, które mogą być (i czasami są) ignorowane przez linker dynamiczny. Przykłady tego można zobaczyć na stronie podręcznika użytkownika dyld . Typową modyfikacją tego zachowania jest użycie zmiennych środowiskowych DYLD_FRAMEWORK_PATH i DYLD_PRINT_LIBRARIES . Pierwsza ze wspomnianych wcześniej zmiennych dostosowuje ścieżkę wyszukiwania plików wykonywalnych dla bibliotek współdzielonych, podczas gdy druga wyświetla nazwy bibliotek podczas ich ładowania i łączenia.

Dynamiczny linker macOS firmy Apple to projekt typu open source wydany jako część Darwin i można go znaleźć w projekcie dyld typu open source firmy Apple .

Systemy uniksopodobne oparte na XCOFF

W systemach operacyjnych typu Unix korzystających z XCOFF , takich jak AIX , dynamicznie ładowane biblioteki współdzielone używają przyrostka nazwy pliku .a .

Można wpłynąć na dynamiczny linker, aby zmodyfikował swoje zachowanie podczas wykonywania programu lub łączenia programu. Typową modyfikacją tego zachowania jest użycie zmiennej środowiskowej LIBPATH . Ta zmienna dostosowuje proces łączenia w czasie wykonywania, wyszukując biblioteki współdzielone w alternatywnych lokalizacjach oraz odpowiednio ładując i łącząc biblioteki, które w innym przypadku nie byłyby dostępne.

OS/360 i następcy

Dynamiczne łączenie z programów języka asemblera w systemie IBM OS/360 i jego następcach odbywa się zwykle przy użyciu makroinstrukcji LINK zawierającej instrukcję Supervisor Call , która aktywuje procedury systemu operacyjnego, dzięki którym moduł biblioteki, który ma być dołączony, jest dostępny dla programu. Moduły biblioteczne mogą znajdować się w „STEPLIB” lub „JOBLIB” określonym na kartach kontrolnych i dostępnym tylko dla określonego wykonania programu, w bibliotece zawartej w LIŚCIE LINKÓW w PARMLIB (określonej podczas uruchamiania systemu) lub w „ link pack area”, w którym określone moduły reentrant są ładowane podczas uruchamiania systemu.

Multiki

W systemie operacyjnym Multics wszystkie pliki, w tym pliki wykonywalne, są segmentami . Wywołanie procedury, która nie jest częścią bieżącego segmentu, spowoduje, że system znajdzie segment, do którego się odwołuje, w pamięci lub na dysku, i doda go do przestrzeni adresowej uruchomionego procesu. Łączenie dynamiczne jest normalną metodą działania, a łączenie statyczne (przy użyciu bindera ) stanowi wyjątek.

Efektywność

Łączenie dynamiczne jest generalnie wolniejsze (wymaga większej liczby cykli procesora) niż łączenie w czasie kompilacji, jak ma to miejsce w przypadku większości procesów wykonywanych w czasie wykonywania. Jednak dynamiczne łączenie jest często bardziej efektywne pod względem miejsca (na dysku iw pamięci w czasie wykonywania). Gdy biblioteka jest powiązana statycznie, każdy uruchamiany proces jest powiązany z własną kopią wywoływanych funkcji bibliotecznych. Dlatego, jeśli biblioteka jest wielokrotnie wywoływana przez różne programy, te same funkcje w tej bibliotece są duplikowane w kilku miejscach w pamięci systemu. Używanie współdzielonych, dynamicznych bibliotek oznacza, że ​​zamiast łączyć każdy plik z jego własną kopią biblioteki w czasie kompilacji i potencjalnie marnować miejsce w pamięci, tylko jedna kopia biblioteki jest zawsze przechowywana w pamięci, zwalniając miejsce w pamięci do używany gdzie indziej. Ponadto w dynamicznym łączeniu biblioteka jest ładowana tylko wtedy, gdy jest faktycznie używana.

Zobacz też

Notatki

Dalsza lektura

Linki zewnętrzne