Динамикалық жүктеу - Dynamic loading

Динамикалық жүктеу а. болатын механизм компьютерлік бағдарлама болады, кезінде жұмыс уақыты, жүктеу а кітапхана (немесе басқасы екілік ) жадқа, кітапхана құрамындағы функциялар мен айнымалылардың адрестерін шығарып алыңыз, оларды орындаңыз функциялары немесе сол айнымалыларға қол жеткізіп, кітапхананы жадтан шығарыңыз. Бұл компьютерлік бағдарлама басқа бағдарламалық жасақтаманы қолдана алатын 3 механизмнің бірі; қалған екеуі статикалық байланыстыру және динамикалық байланыстыру. Статикалық байланыстыру мен динамикалық байланыстырудан айырмашылығы, динамикалық жүктеу а компьютерлік бағдарлама осы кітапханалар болмаған кезде бастау, қол жетімді кітапханаларды табу және қосымша функционалдылыққа ие болу.[1][2]

Тарих

Динамикалық жүктеу IBM үшін кең таралған әдіс болды операциялық жүйелер үшін Жүйе / 360 сияқты OS / 360, әсіресе Енгізу / шығару ішкі бағдарламалар, және үшін COBOL және PL / I жұмыс уақыты кітапханалары, және IBM операциялық жүйелерінде қолданылуы жалғасуда z / Сәулет, сияқты z / OS. Қолданбалы бағдарламалаушыға келетін болсақ, жүктеме көбіне мөлдір, өйткені оны көбінесе операциялық жүйе (немесе оның енгізу-шығару ішкі жүйесі) басқарады. Негізгі артықшылықтары:

  • Түзетулер (патчтар ) ішкі жүйелерге барлық бағдарламаларды қайта қосудың қажеті жоқ бірден тіркеді
  • Кітапханалар рұқсат етілмеген өзгертулерден қорғалуы мүмкін

IBM стратегиялық транзакцияны өңдеу жүйе, CICS (1970 ж. Бастап) ол үшін де динамикалық жүктемені кеңінен қолданады ядро және қалыпты жағдай үшін қолданбалы бағдарлама жүктеу. Қолданбалы бағдарламаларға түзетулер офлайн режимінде енгізілуі мүмкін және өзгертілген бағдарламалардың жаңа көшірмелері CICS қайта қосуды қажет етпестен динамикалық түрде жүктелуі мүмкін.[3][4] (ол жұмыс істей алады және жиі жұмыс істейді 24/7 ).

Ортақ кітапханалар 1980 жылдары Unix-ке қосылды, бірақ бастапқыда бағдарлама іске қосылғаннан кейін қосымша кітапханаларды жүктеуге мүмкіндік бермейді.[5]

Қолданады

Динамикалық жүктеу көбінесе іске асыруда қолданылады бағдарламалық жасақтама плагиндері.[1] Мысалы, Apache веб-сервері * .dso «динамикалық ортақ нысан» плагин файлдары кітапханалар олар динамикалық жүктеумен жұмыс уақытында жүктеледі.[6] Жүзеге асыруда динамикалық жүктеме де қолданылады компьютерлік бағдарламалар мұнда бірнеше әртүрлі кітапханалар қажетті функционалдылықты қамтамасыз ете алады және пайдаланушыда қандай кітапхана немесе кітапханалар ұсынылатынын таңдау мүмкіндігі бар.

C / C ++ тілінде

Барлық жүйелер динамикалық жүктеуді қолдамайды. UNIX тәрізді сияқты операциялық жүйелер macOS, Linux, және Solaris динамикалық жүктеуді қамтамасыз етеді C бағдарламалау тілі «dl» кітапханасы. The Windows операциялық жүйе арқылы динамикалық жүктеуді қамтамасыз етеді Windows API.

Қысқаша мазмұны

Аты-жөні Стандартты POSIX / UNIX API Microsoft Windows API
Тақырып файлын қосу # қосыңыз # қосыңыз
Тақырыпқа арналған анықтамалар dl

(libdl.so, libdl.dylibбайланысты және т.б. ОЖ )

kernel32.dll
Кітапхана жүктелуде допен Кітапхана жүктеу
LoadLibraryEx
Мазмұнды шығару dlsym GetProcAddress
Кітапханадан түсіру dlclose FreeLibrary

Кітапхана жүктелуде

Кітапхананы жүктеу жұмыстары аяқталды Кітапхана жүктеу немесе LoadLibraryEx қосулы Windows және бірге допен қосулы UNIX тәрізді операциялық жүйелер. Мысалдар келесідей:

UNIX тәрізді операциялық жүйелердің көпшілігі (Solaris, Linux, * BSD және т.б.)

жарамсыз* sdl_library = допен(«libSDL.so», RTLD_LAZY);
егер (sdl_library == ЖОҚ) {
   // есеп қатесі ...
} басқа {
   // нәтижені dlsym-ге шақыру кезінде қолданыңыз
}

MacOS

Сияқты UNIX кітапхана:

жарамсыз* sdl_library = допен(«libsdl.dylib», RTLD_LAZY);
егер (sdl_library == ЖОҚ) {
   // есеп қатесі ...
} басқа {
   // нәтижені dlsym-ге шақыру кезінде қолданыңыз
}

Сияқты macOS Framework:

жарамсыз* sdl_library = допен(«/Library/Frameworks/SDL.framework/SDL», RTLD_LAZY);
егер (sdl_library == ЖОҚ) {
   // есеп қатесі ...
} басқа {
   // нәтижені dlsym-ге шақыру кезінде қолданыңыз
}

Немесе егер рамкада немесе бумада Objective-C коды болса:

NSBundle *байлам = [NSBundle bundleWithPath:@ «/ Library / Plugins / Plugin.bundle»];
NSEқатесі *қате = нөл;
егер ([байлам loadAndReturnError:&қате])
{
    // Бумадағы кластар мен функцияларды қолданыңыз.
}
басқа
{
    // Қате.
}

Windows

HMODULE sdl_library = Кітапхана жүктеу(МӘТІН(«SDL.dll»));
егер (sdl_library == ЖОҚ) {
   // есеп қатесі ...
} басқа {
   // нәтижені шақыруда қолданыңыз GetProcAddress
}

Кітапхана мазмұнын шығару

Динамикалық жүктелген кітапхананың мазмұнын алуға қол жеткізіледі GetProcAddress қосулы Windows және бірге dlsym қосулы UNIX - тәрізді операциялық жүйелер.

UNIX тәрізді операциялық жүйелер (Solaris, Linux, * BSD, macOS және т.б.)

жарамсыз* инициализатор = dlsym(sdl_library,«SDL_Init»);
егер (инициализатор == ЖОҚ) {
   // есеп қатесі ...
} басқа {
   // инициализаторды тиісті түріне және қолданылуына құйыңыз
}

MacOS-та Objective-C бумаларын пайдалану кезінде мыналарды да жасауға болады:

Сынып rootClass = [байлам principalClass]; // Сонымен қатар, NSClassFromString () атауы бойынша класты алуға болады.
егер (rootClass)
{
    идентификатор объект = [[rootClass бөлу] ішінде]; // Нысанды қолданыңыз.
}
басқа
{
    // Қате туралы есеп беру.
}

Windows

FARPROC инициализатор = GetProcAddress(sdl_library,«SDL_Init»);
егер (инициализатор == ЖОҚ) {
   // есеп қатесі ...
} басқа {
   // инициализаторды тиісті түріне және қолданылуына құйыңыз
}

Кітапхана функциясының көрсеткішін түрлендіру

Нәтижесі dlsym () немесе GetProcAddress () оны қолданар алдында сәйкес типтегі көрсеткішке ауыстыру керек.

Windows

Windows жағдайында конверсия тікелей болады, өйткені FARPROC функциясы қазірдің өзінде функцияның нұсқаушысы болып табылады:

typedef INT_PTR (*FARPROC)(жарамсыз);

Бұл функцияны емес, объектінің адресін алу керек болғанда проблемалы болуы мүмкін. Алайда, әдетте, кез-келген функцияны бөліп алғысы келеді, сондықтан бұл әдетте қиындық тудырмайды.

typedef жарамсыз (*sdl_init_function_type)(жарамсыз);
sdl_init_function_type init_func = (sdl_init_function_type) инициализатор;

UNIX (POSIX)

POSIX спецификациясына сәйкес dlsym () Бұл жарамсыз көрсеткіш. Алайда, функция көрсеткіші үшін деректер объектісінің көрсеткішімен бірдей өлшемнің болуы талап етілмейді, сондықтан тип арасындағы дұрыс түрлендіру жарамсыз * және функцияға сілтегішті барлық платформаларда орындау оңай болмауы мүмкін.

Қазіргі кезде қолданылатын жүйелердің көпшілігінде функция мен объект көрсеткіштері қолданылады іс жүзінде айырбасталатын. Келесі код үзіндісі көптеген жүйелерде конверсияны жүзеге асыруға мүмкіндік беретін бір уақытша шешімді көрсетеді:

typedef жарамсыз (*sdl_init_function_type)(жарамсыз);
sdl_init_function_type init_func = (sdl_init_function_type)инициализатор;

Жоғарыдағы үзінді кейбір компиляторларға ескерту береді: ескерту: түрлендірілген нұсқағышты ажырату қатаң лақап ережелерін бұзады. Тағы бір шешім:

typedef жарамсыз (*sdl_init_function_type)(жарамсыз);
одақ { sdl_init_function_type функциясы; жарамсыз * obj; } бүркеншік ат;
бүркеншік ат.obj = инициализатор;
sdl_init_function_type init_func = бүркеншік ат.функциясы;

бұл қатаң бүркеншік күші болса да ескертуді өшіреді. Бұл басқа кәсіподақ мүшелерінен жақында жазылған (оқылған) оқудан оқуды қолданадытүрлендіру «) кең таралған, және қатаң бүркеншік ат күші болған жағдайда да, егер жадқа тікелей одақ типі арқылы қол жеткізілсе, нақты рұқсат етіледі.[7] Алайда, бұл жерде бұл қатаң емес, өйткені функция көрсеткіші одақтан тыс жерде пайдалану үшін көшірілген. Бұл трюк деректердің көрсеткіштері мен функционалды көрсеткіштердің өлшемдері бірдей емес платформаларда жұмыс істемеуі мүмкін екенін ескеріңіз.

POSIX жүйелеріндегі функция көрсеткішінің мәселесін шешу

Функция мен деректер нысаны көрсеткіштері арасындағы кез-келген түрлендіруді (табиғи түрде портативті емес) іске асырудың кеңеюі ретінде қарастыру қажет және тікелей түрлендірудің «дұрыс» тәсілі жоқ, өйткені POSIX және ISO стандарттары қайшы келеді бір-бірін.

Бұл мәселеге байланысты POSIX құжаттамасы dlsym () ескірген 6-шы шығарылым үшін «болашақ нұсқасы функция көрсеткіштерін қайтару үшін жаңа функция қосуы мүмкін, немесе қазіргі интерфейс екі жаңа функцияның пайдасына күшін жояды: біреуі дерек көрсеткіштерін қайтарады, ал екіншісі функция сілтемелерін қайтарады».[8]

Стандарттың келесі нұсқасы үшін (7 шығарылым, 2008 ж.) Проблема талқыланды және функция көрсеткіштері конверттелетін болуы керек деген қорытынды келді жарамсыз * POSIX сәйкестігі үшін.[8] Бұл компилятор жасаушылардан осы жағдайға арналған жұмыс тобын іске асыруды талап етеді.

Егер кітапхананың мазмұнын өзгертуге болатын болса (яғни, арнайы кітапхана жағдайында), функциядан басқа оған сілтеме де экспортталуы мүмкін. Функция сілтегішінің өзі объектінің көрсеткіші болғандықтан, оны кез келген уақытта қоңырау арқылы заңды түрде алуға болады dlsym () және кейінгі конверсия. Алайда, бұл тәсіл сыртта қолданылатын барлық функцияларға жеке көрсеткіштерді сақтауды қажет етеді, ал оның пайдасы әдетте аз болады.

Кітапханадан түсіру

Кітапхананы жүктеу жадтың бөлінуіне әкеледі; а болдырмау үшін кітапхананы бөлу керек жадтың ағуы. Сонымен қатар, кітапхананың жүктемесін болдырмауға болады файлдық жүйе бойынша операциялар файл кітапхана бар. Кітапхананы түсіру арқылы жүзеге асырылады FreeLibrary қосулы Windows және бірге dlclose UNIX сияқты операциялық жүйелер. Алайда, егер негізгі қолданбадағы нысандар DLL ішінде бөлінген жадқа сілтеме жасаса, DLL-ді түсіру бағдарламаның бұзылуына әкелуі мүмкін. Мысалы, егер DLL жаңа класс енгізсе және DLL жабық болса, онда негізгі қосымшадан осы сыныптың даналарында жүргізілетін одан әрі әрекеттер жадқа кірудің бұзылуын тудыруы мүмкін. Сол сияқты, егер DLL динамикалық жүктелген сыныптарды құруға арналған зауыттық функцияны енгізсе, DLL жабылғаннан кейін бұл функцияны шақыру немесе кейінге қалдыру анықталмаған әрекетке әкеледі.

UNIX тәрізді операциялық жүйелер (Solaris, Linux, * BSD, macOS және т.б.)

dlclose(sdl_library);

Windows

FreeLibrary(sdl_library);

Арнайы кітапхана

Динамикалық жүктеуді енгізу UNIX тәрізді операциялық жүйелер және Windows бағдарламашыларға ағымдағы орындалатын процесстің шартты белгілерін шығаруға мүмкіндік беру.

UNIX тәрізді операциялық жүйелер бағдарламашыларға негізгі орындалатын және кейіннен жүктелген динамикалық кітапханаларды қамтитын ғаламдық символдық кестеге қол жеткізуге мүмкіндік береді.

Windows бағдарламашыларға негізгі орындалатын файлмен экспортталған символдарға қол жеткізуге мүмкіндік береді. Windows ғаламдық белгілер кестесін пайдаланбайды және бірнеше модуль бойынша іздеу үшін API жоқ, символды аты бойынша табу.

UNIX тәрізді операциялық жүйелер (Solaris, Linux, * BSD, macOS және т.б.)

жарамсыз* осы_процесс = допен(ЖОҚ,0);

Windows

HMODULE осы_процесс = GetModuleHandle(ЖОҚ);

HMODULE осы_процесс_қайта;
GetModuleHandleEx(0,0,&осы_процесс_қайта);

Java-да

Ішінде Java бағдарламалау тілі, сыныптар көмегімен динамикалық түрде жүктеуге болады ClassLoader объект. Мысалға:

Сынып түрі = ClassLoader.getSystemClassLoader().loadClass(аты);
Нысан obj = түрі.newInstance();

Рефлексия механизмі, егер ол жүктелмеген болса, классты жүктеу құралын ұсынады. Онда ағымдағы сыныптың класс жүктегіші қолданылады:

Сынып түрі = Сынып.forName(аты);
Нысан obj = түрі.newInstance();

Алайда, сыныпты бақыланатын тәсілмен түсірудің қарапайым әдісі жоқ. Жүктелген кластарды тек бақыланатын әдіспен түсіруге болады, яғни бағдарламашы мұның болғанын қалаған кезде, егер класты жүктеу үшін қолданылатын сынып тиегіші жүйелік класс жүктеушісі болмаса және өзі жүктелмеген болса. Мұны істегенде, сыныптың шынымен де босағанын қамтамасыз ету үшін әртүрлі бөлшектерді байқау керек. Бұл сабақтарды түсіруді жалықтырады.

Сыныптарды жасырын түсіру, яғни қоқыс жинаушы бақылаусыз түрде, Java-да бірнеше рет өзгерді. Java 1.2 дейін. қоқыс жинаушы сыныпты жүктеу үшін қандай сынып тиегішінен тәуелсіз, орын қажет болған кезде сыныпты түсіре алады. Java 1.2 жүйесінен бастап жүйелік класс жүктегіш арқылы жүктелген сыныптар ешқашан түсірілмейді және сыныптар басқа класс жүктегіштер арқылы жүктелетін кезде ғана жүктеледі. Java 6 сыныптарынан бастап қоқыс жинаушыға арналған ішкі маркерді қамтуы мүмкін, егер олар қоқыс жинағыш мұны қаласа, сыныпты жүктеу үшін қолданылатын сынып тиегішінен тәуелсіз. Қоқыс жинаушы бұл кеңесті елемеуі мүмкін.

Сол сияқты жергілікті әдістерді іске асыратын кітапханалар. Динамикалық түрде жүктеледі System.loadLibrary әдіс. Жоқ System.unloadLibrary әдіс.

Динамикалық жүктемесіз платформалар

1980 жылдары UNIX және Windows арқылы шыққанына қарамастан, кейбір жүйелер әлі де динамикалық жүктеуді қоспауды, тіпті алып тастауды шешпеді. Мысалға, Bell Labs компаниясының 9-жоспары және оның мұрагері 9front әдейі динамикалық байланыстырудан аулақ болады, өйткені олар оны «зиянды» деп санайды.[9] The Бағдарламалау тіліне өтіңіз, 9-жоспар сияқты кейбір әзірлеушілер динамикалық байланыстыруды қолдамады, бірақ плагинді жүктеу содан бері қол жетімді 1.8 өту (Ақпан 2017). Go жұмыс уақыты және кез-келген кітапхананың функциялары жинақталған екілік жүйеге статикалық түрде байланысты.[10]

Сондай-ақ қараңыз

Әдебиеттер тізімі

  1. ^ а б Autoconf, Automake және Libtool: динамикалық жүктеу
  2. ^ «Linux4U: ELF Dynamic жүктеу». Архивтелген түпнұсқа 2011-03-11. Алынған 2007-12-31.
  3. ^ «Қолданбалы бағдарламаларды орнату үшін CICS ұсынған процедураларды қолдану».
  4. ^ «IBM CEMT NEWCOPY немесе PHASEIN сұранысы HOLD PROG FOR NOT - АҚШ-та орындалмады». 2013-03-15.
  5. ^ Хо, Уилсон; Олссон, Рональд А. (1991). «Шынайы динамикалық байланыстыру тәсілі». Бағдарламалық жасақтама - тәжірибе және тәжірибе. 21 (4): 375–390. CiteSeerX  10.1.1.37.933. дои:10.1002 / спе.4380210404.
  6. ^ Apache 1.3 Dynamic Shared Object (DSO) қолдауы
  7. ^ GCC 4.3.2 Оптимизация опциялары: қатаң лақап ат
  8. ^ а б POSIX құжаттамасы допен () (6 және 7 шығарылымдар).
  9. ^ «Динамикалық байланыстыру». cat-v.org. 9front. Алынған 2014-12-22.
  10. ^ «Жиі қойылатын сұрақтар».

Әрі қарай оқу

  • Сильбершатц, Авраам; Гальвин, Питер Баер; Гагне, Грег (2005). «8.1.4 тарау» Динамикалық жүктеу «және 8.1.5 тарау» Динамикалық байланыстыру және ортақ кітапханалар"". Операциялық жүйе туралы түсініктер. Дж. Вили және ұлдары. ISBN  978-0-471-69466-3.

Сыртқы сілтемелер