Dynamický linker

Dynamický linker označuje ve výpočetní technice část operačního systému (OS), která načítá (kopíruje z perzistentního úložiště do operační paměti) a kde linker propojuje (vyplňuje tabulky skoků a mění ukazatele) na funkce ve sdílených knihovnách se spustitelným programem za běhu programu. Specifický formát spustitelných souborů je jiný pro každý operační systém. Tento formát určuje rozhraní linkeru a jeho implementaci.

Linkováním je často označován proces, který je prováděn během kompilace spustitelného programu. Zatím co dynamický linker je ve skutečnosti speciální zavaděč, který načte externí sdílené knihovny do adresního prostoru běžícího spustitelného programu a potom je s ním sváže. Toto je také nazýváno dynamické nebo také zpožděné linkování.

Implementace

Microsoft Windows

Dynamicky linkované knihovny, zkráceně DLL, je implementace sdílených knihoven v operačních systémech Microsoft Windows a OS/2, kterou zavedl Microsoft. Tyto knihovny lze běžně nalézt s příponou DLL, OCX (knihovny obsahující ActiveX), nebo DRV (pro zastaralé systémové ovladače). Formát těchto souborů je stejný jako formát spustitelných souborů EXE, což je Portable Executable (PE) pro 32bitové a 64bitové Windows, a New Executable (NE) pro 16bitové Windows. Stejně jako EXE soubory, DLL soubory mohou obsahovat strojový kód, data a zdroje (zdrojem je ve Windows např. ikona) a to libovolně kombinované.

Soubory se stejným formátem jako DLL, ale s jinou příponou (a také obsahující jen windows zdroje) mohou být nazývány zdrojové DLL. Příklady těchto zdrojových DLL knihoven jsou knihovny ikon, které občas mají příponu ICL a knihovny obsahující fonty, které mají příponu FON a FOT.

Unix-like systémy na ELF základu

Na většině Unix-like systémech, které používají ELF formát pro spustitelné obrázky a dynamické knihovny, je většina strojového kódu, který tvoří dynamický linker, ve skutečnosti externí spustitelný soubor, který je načten jádrem operačního systému. Jádro operačního systému spustí tento kód jako první v adresním prostoru vzniklém výsledkem systémového volání exec nebo voláním posix_spawn. Během kompilování je použita cesta k dynamickému linkeru, který by měl být posazený do .interp sekce spustitelného programu. Jádro operačního systému čte tuto část programu během vytváření nového procesu, poté načte a spustí tento kód cesty ke knihovně. Dynamický linker poté načte inicializační obraz spustitelného souboru a všechny dynamicky linkované knihovny na kterých závisí a poté spustí samotný spustitelný program. V Unix-like operačních systémech používajících ELF mohou být dynamicky načítané sdílené knihovny identifikované příponou .so (sdílený objekt).

Dynamický linker může být ovlivněn ke změně svého chování za běhu programu nebo během linkování programu. Příklady tohoto chování můžeme pro mnoho systémů vidět v manuálových stránkách run-time linkeru.[1][2][3][4][5] Typickou modifikací tohoto chování je použití LD_LIBRARY_PATH a LD_PRELOAD proměnných prostředí. Tyto proměnné upravují runtime linkovací proces hledáním sdílených knihoven na alternativních místech, násilným načítáním a linkováním knihoven, které by jinak načteny a nalinkovány nebyly. Příklad lze nalézt v zlibc[6] také známe jako uncompress.so (neplést si s zlib kompresní knihovnou zlib.[7] Tento LD_PRELOAD hack používá transparentní dekompresi, tedy čtení zkomprimovaných dat (gzippem) na BSD a Linux systémech tak, jako by vůbec nebyla komprimována. To v zásadě umožňuje uživateli předstírat, že nativní souborový systém podporuje transparentní komprimování, přestože tento přístup má nějaké potíže. Tento mechanismus je natolik flexibilní, že podporuje adopci stejného kódu pro čtení jak komprimovaných tak nekomprimovaných dat.

GNU/Linux

Operační systémy založené na GNU/Linux implementují model dynamického linkeru, kde část spustitelného programu obsahuje velmi jednoduchý kus linkeru. Ten donutí systém k načtení externí knihovny do paměti. Tento kus linkeru je přidán do spustitelného programu během kompilace tohoto programu. Účel tohoto kusu linkeru je načíst skutečný dynamický linker do paměti a začít proces dynamického linkování spuštěním tohoto svého skutečného linkeru. Design operačního systému říká, že spustitelný program by měl zavést dynamický linker před spuštěním své hlavní funkce. Přesto je tento mechanismus implementován jinak. Systém ví, kde se v systému nachází dynamický linker a přiřadí ho k nově vytvořenému procesu. Kus linker kódu, který je součástí spustitelného programu se sice provede, ale linker už je dávno součástí procesu. Důvod této změny je, že formát ELF binárního souboru byl navržen pro několik na Unixu založených systémů, ne jen GNU/Linux.[8]

Zdrojový kód pro GNU/Linux linker je součástí glibc projektu a je volně dostupný na stránce projektu.[9] Celý zdrojový kód je dostupný pod licencí GNU LGPL.

OS X and iOS

U operačního systému Darwin a u operačních systémů OS X a iOS, které jsou na něm postavené, je většina strojového kódu, který tvoří dynamický linker, ve skutečnosti externí spustitelný soubor, který je načten jádrem operačního systému. Jádro operačního systému spustí tento kód jako první v adresním prostoru vzniklém výsledkem exec a nebo posix_spawn voláním. Během kompilování je použita cesta k dynamickému linkeru, který by měl být posazený do jednoho z Mach-O načítacích příkazů. Jádro operačního systému čte tuto část programu během vytváření nového procesu, poté načte a spustí tento kód cesty ke knihovně. Dynamický linker nejen že spojuje standardní knihovny se spustitelným programem, ale také vloží funkce ve strojovém kódu na specifická místa v paměti, takže spustitelný program ví přesně, kde je může nalézt. Pokud si spustitelný program přeje pracovat s dynamickým linkerem, jednoduše skočí na instrukci jedné z těchto dobře známých adres. Spustitelné programy na OS X a iOS platformách často komunikují s dynamickým linkerem během výkonu programu. Je dokonce známé, že spustitelný program může požádat linker o načtení knihovny nebo symbolu hodiny po svém spuštění. Důvody pro tuto častou interakci spustitelného programu a dynamického linkeru na platformách OS X a iOS jsou dva. Jedním je Apple Cocoa a Cocoa Touch API a druhým je Objective-C, jazyk, ve kterém jsou tyto spustitelné soubory implementovány (více informací lze nalézt v článcích zaměřených na tyto technologie). Na Darwin systému založených platformách lze sdílené knihovny rozlišit buďto podle přípony .dylib, nebo jejich umístěním uvnitř bundle ve frameworku.

Dynamický linker může být donucen k modifikaci svého chování, ale na rozdíl od ostatních na Unixu založených systémů jsou tyto pokyny k modifikaci brány jen jako doporučení, která mohou být (o občas jsou) ignorována dynamickým linkerem. Příklad takového chování je k vidění v dyld manuálové stránce.[10] Typickou modifikací chování linkeru je použití DYLD_FRAMEWORK_PATH a DYLD_PRINT_LIBRARIES proměnných prostředí. Tyto proměnné upravují cestu, na které spustitelný soubor hledá sdílené knihovny a tisknou názvy knihoven tak, jak jsou načítány (v tomto pořadí).

Zdrojový kód k dynamickému linkeru od Apple OS X je open source a zveřejněn jako součást Darwin operačního systému. Může být k nalezení v dyld projektu na Apple open source webové stránce[11]

Unix-like systémy na XCOFF základu

V Unix-like operačních systémech používajících XCOFF mají dynamicky načítané sdílené knihovny příponu .a.

Dynamický linker může být ovlivněn k modifikaci svého chování během výkonu programu, nebo během linkování programu. Typickou modifikací takového chování je použití proměnné prostředí LIBPATH. Tato proměnná upravuje linkovací proces nastavením alternativní cesty k hledání sdílených knihoven.

OS/360 and successors

Dynamické linkování z programů napsaných v Assembleru je v systémech 0S/360 a jeho potomcích běžně prováděno používáním LINK makro instrukce obsahující „instrukci volání nadřízeného“, která aktivuje část operačního systému, která spojí modul sdílené knihovny se spustitelným programem. Moduly sdílených knihoven se nachází v STEPLIB nebo JOBLIB specifikovaných v kontrolních kartách a přístupných pouze pro specifický spustitelný program, pro knihovnu obsaženou v LINKLIST v PARAMLIB proměnné (specifikované během spuštění systému), nebo pro „link pack area“ kam se načítají některé moduly během spuštění systému.

Reference

  1. ld.so.1: Solaris – Solaris dynamic linker/loader – Solaris 10 User Commands Reference Manual
  2. ld-linux.so(8): Linux Programmer's Manual – Administration and Privileged Commands
  3. rtld(1): FreeBSD dynamic linker/loader – FreeBSD General Commands Manual
  4. ld.elf_so(1): NetBSD dynamic linker/loader – NetBSD General Commands Manual
  5. ld.so(1): OpenBSD dynamic linker/loader – OpenBSD General Commands Manual
  6. ftp://metalab.unc.edu/pub/Linux/libs/compression/zlibc-0.9k.lsm[nedostupný zdroj]
  7. domácí stránka knihovny zlib
  8. Understanding the Linux Kernel, O'REILLY, 3rd Edition, Chapter 20
  9. domácí webová stránka GNU
  10. dyld(1): Darwin/Mac OS X dynamic linker/loader – Darwin and Mac OS X General Commands Manual
  11. Apple Inc. Open Source - Releases [online]. apple.com [cit. 2014-07-04]. Dostupné online. (anglicky) 

Související články

Literatura

  • Linkers and Loaders, John R. Levine, Morgan-Kauffman, October 1999, ISBN 1-55860-496-0

Externí odkazy