Dynamic loading (dynamické načítání) je v informatice označení pro mechanismus, který načte knihovnu do paměťového prostoru za běhu procesu. Běžící proces tak získá možnost volat procedury a funkce, které se nacházejí v načtené knihovně. Knihovnu lze později z paměti uvolnit. Mechanismus umožňuje programátorovi v případě nedostupnosti knihovny provést náhradní činnost (použít alternativní knihovnu, zobrazit hlášení uživateli a podobně). Tím se odlišuje od klasického zavádění dynamických knihoven při spuštění programu, kdy musí být přítomny všechny potřebné knihovny.
Historie Dynamické načítání bylo běžným mechanismem pro operační systém IBM/360 (začátek 60. let až do současné Z/Architektury) a to zejména pro obsluhu vstupně-výstupních rutin, COBOL a PL/1 běhových knihoven. Co se týče programování aplikací, nahrávání je do značné míry transparentní, protože je většinou vyřešené na úrovni operačního systému. IBM využívá dynamické načtení od 70. let 20. století u transakčního zpracování strategického systému CICS a to jak pro jádro operačního systému, tak i pro normální aplikační programy. Opravy pak mohou být uskutečněny za běhu systému nebo programu bez nutnosti jejich restartu.
Mezi hlavní výhody patří: opravy subsystému opravují celý program bez nutnosti jeho nového linkování knihovny mohou být chráněny před neautorizovanou úpravou
Použití Dynamické načítání je nejčastěji používáno v implementaci softwarových pluginů (modulární struktura Apache HTTP Serveru). Nebo v programech, které nabízejí více podporovaných knihoven a uživatel si je jednotlivě může volit (rozšiřující knihovny pro PHP).
C/C++ Dynamické načítání nepodporují všechny systémy. Mac OS X, Linux a Solaris nabízí dynamické načítání prostřednictvím knihovních „dl“ funkcí v jazyce C. Operační systém Windows podporuje dynamické načítání pomocí volání Windows API.
Shrnutí Název Standard POSIX/UNIX API Microsoft Windows API Zařazení hlavičkového souboru #include <dlfcn.h> #include <windows.h> Definice hlavičky dl (libdl.so, libdl.dylib, závisí na operačním systému) Kernel32.dll Načtení knihovny dlopen LoadLibraryLoadLibraryEx Extrahování obsahu dlsym GetProcAddress Zavření knihovny dlclose FreeLibrary
Načtení knihovny Načtení knihovny se provede prostřednictvím LoadLibrary nebo LoadLibraryEx na operačním systému Windows a pomocí dlopen na operačních systémech na bázi Linuxu. Následují příklady:
Linux, *BSD, Solaris, etc. void* sdl_library = dlopen("libSDL.so", RTLD_LAZY); if(sdl_library == NULL) { // oznámení chyby ... } else { // výsledek zavoláním dlsym }
Mac OS X UNIX library: void* sdl_library = dlopen("libsdl.dylib", RTLD_LAZY); if(sdl_library == NULL) { // oznámení chyby ... } else { // výsledek zavoláním dlsym } OS X Framework: void* sdl_library = dlopen("/Library/Frameworks/SDL.framework/SDL", RTLD_LAZY); if(sdl_library == NULL) { // oznámení chyby ... } else { // výsledek zavoláním dlsym }
Windows HMODULE sdl_library = LoadLibrary("SDL.dll"); if( sdl_library == NULL) { //oznámení chyby ... } else { // výsledek zavoláním GetProcAddress }
Extrahování obsahu knihovny Extrahování obsahu dynamicky načítané knihovny je dosaženo pomocí příkazu GetProcAddress ve Windows a dlsym v Unix systému.
Linux, *BSD, Mac OS X, Solaris, etc. void* initializer = dlsym(sdl_library,"SDL_Init"); if(initializer == NULL) { // oznámení chyby ... } else { ... }
Windows FARPROC initializer = GetProcAddress(sdl_library,"SDL_Init"); if(initializer == NULL) { // report error ... } else { ... }
Převod extrahovaného obsahu knihovny Vrácený výsledek prostřednictvím dlsym() nebo GetProcAddress() musí být převeden do požadované destinace předtím, než může být použit.
Windows V případě systému Windows, konverze je jednoduchá, protože FARPROC je v podstatě již ukazatel funkce: typedef INT_PTR (*FARPROC)(void); Může nastat problém, pokud adresy objektu jsou vyvolány místo funkce. Nicméně, obvykle jeden chce získat funkce stejně, takže to není ve výsledku problém. typedef void (*sdl_init_function_type)(void); sdl_init_function_type init_func = (sdl_init_function_type) initializer;
UNIX (POSIX) Dle specifikace POSIX je výsledkem provedení dlsym() prázdný ukazatel (pointer), což způsobuje problém. Je to způsobeno tím, že programovací jazyky C a C++ nedovolují provést konverzi mezi ukazateli na objekty a ukazateli funkcí (není vyžadováno aby měl ukazatel funkce stejnou velikost jako ukazatel na objekt). Je tedy striktně zakázáno provést konverzi mezi typem void* a ukazatelem na funkci. Na většině v současnosti používaných systémů jsou ukazatele na funkce s ukazateli na objekty mezi sebou již konvertibilní.
Následující fragment kódu ukazuje jeden ze způsobů řešení, který umožňuje provádět tuto konverzi v různých systémech:
typedef void (*sdl_init_function_type)(void); sdl_init_function_type init_func = (sdl_init_function_type)initializer;
Výše uvedená část programového kódu může u některých kompilátorů vyvolat toto varovné hlášení: „Přejmenování ukazatele dereferenčního typu porušuje pravidla aliasingu“. Řešením je použití následujícího programového kódu:
typedef void (*sdl_init_function_type)(void); union { sdl_init_function_type func; void * obj; } alias; alias.obj = initializer; sdl_init_function_type init_func = alias.func;
Tím se zakáže varovné hlášení.
Související články Knihovna (programování) DLL
Externí odkazy General Links Dynamic Loading on Linux4U Dynamic Shared Object (DSO) Support by Apache C++ Dynamic Linking By Example Dynamic Library Programming Topics from Apple Developer Connection (target to Mac OS X) C/C++ UNIX API: dlopen dlsym dlclose C/C++ Windows API: LoadLibrary GetProcAddress FreeLibrary Delay-Loaded DLLs Java API: ClassLoader Class
Kategorie:Operační systém Kategorie:Programové knihovny Kategorie:Anglická slova a fráze