동적 부하

Dynamic loading

동적 로딩은 컴퓨터 프로그램실행라이브러리(또는 다른 바이너리)를 메모리에 로드하고 라이브러리에 포함된 함수 및 변수의 주소를 검색하여 이러한 함수를 실행하거나 이러한 변수에 액세스하고 라이브러리를 메모리에서 언로드할 수 있는 메커니즘입니다.이것은 컴퓨터 프로그램이 다른 소프트웨어를 사용할 수 있는 세 가지 메커니즘 중 하나이며, 나머지 두 가지는 정적 링크동적 링크입니다.정적 링크 및 동적 링크와 달리 동적 로딩은 이러한 라이브러리가 없는 상태에서 컴퓨터 프로그램을 시작하고 사용 가능한 라이브러리를 검색하여 추가 기능을 [1][2]얻을 수 있습니다.

역사

동적 로딩은 OS/360과 같은 시스템/360용 IBM 운영 체제, 특히 I/O 서브루틴과 COBOLPL/I 런타임 라이브러리의 일반적인 기술이었으며 z/OS와 같은 IBM의 z/Architecture용 운영 체제에서 계속 사용되고 있습니다.애플리케이션 프로그래머에 관한 한 로드는 대부분 운영체제(또는 그 I/O 서브시스템)에 의해 처리되기 때문에 거의 투명합니다.주요 장점은 다음과 같습니다.

  • 수정한 모든 프로그램을 한 번에 수정(패치)하여 다시 링크할 필요가 없음
  • 라이브러리는 무단 변경으로부터 보호될 수 있습니다.

IBM의 전략적 트랜잭션 처리 시스템인 CICS(1970년대 이후)는 커널과 일반 애플리케이션 프로그램 로딩 모두에 동적 로딩을 광범위하게 사용합니다.애플리케이션 프로그램을 오프라인으로 수정하고 변경된 프로그램의 새 복사본을 동적으로 로드할 수 있습니다. CICS를 재시작할[3][4] 필요가 없습니다(대부분 24시간 365일 실행 가능).

공유 라이브러리는 1980년대에 유닉스에 추가되었지만 처음에는 프로그램이 시작 [5]후에 추가 라이브러리를 로드하도록 하는 기능이 없었다.

사용하다

동적 로딩은 소프트웨어 [1]플러그인을 구현하는 데 가장 많이 사용됩니다.를 들어 Apache Web 서버의 *.dso"동적 공유 개체" 플러그인 파일은 런타임에 동적 [6]로딩과 함께 로드되는 라이브러리입니다.동적 로딩은 여러 개의 다른 라이브러리가 필요한 기능을 제공하고 사용자가 제공할 라이브러리를 선택할 수 있는 컴퓨터 프로그램을 구현하는 데도 사용됩니다.

입력 C/C++

일부 시스템에서는 동적 로드를 지원하지 않습니다.MacOS, LinuxSolaris와 같은 UNIX와 유사한 운영체제는 C 프로그래밍 언어 "dl" 라이브러리를 사용하여 동적으로 로딩합니다.Windows 운영체제Windows API를 통해 동적 로드를 제공합니다.

요약

이름. 표준 POSIX/UNIX API Microsoft Windows API
헤더 파일 포함 #include <dlfcn.h> #include <windows.h>
헤더의 정의 dl

(libdl.so,libdl.dylib(OS에 따라 다릅니다.)

kernel32.dll
라이브러리 로드 중 dlopen LoadLibrary
LoadLibraryEx
내용 추출 중 dlsym GetProcAddress
라이브러리 언로드 dlclose FreeLibrary

라이브러리 로드 중

라이브러리 로드는 다음과 같이 수행합니다.LoadLibrary또는LoadLibraryExWindows 및 를 사용하여dlopen operating system에 대응하고 있습니다.다음은 예를 제시하겠습니다.

대부분의 UNIX 계열 운영체제(Solaris, Linux, *BSD 등)

무효* sdl_module = 열리다("libSDL.so", RTLD_LAZy); 한다면 (sdl_module == 특수한 순서) {    // 오류 보고... } 또 다른 {    // 결과를 dlsym 호출에 사용합니다. } 

MacOS

UNIX 라이브러리의 경우:

무효* sdl_module = 열리다("libSDL.dylib", RTLD_LAZy); 한다면 (sdl_module == 특수한 순서) {    // 오류 보고... } 또 다른 {    // 결과를 dlsym 호출에 사용합니다. } 

macOS 프레임워크로서:

무효* sdl_module = 열리다("/라이브러리/프레임워크/SDL.프레임워크/SDL", RTLD_LAZy); 한다면 (sdl_module == 특수한 순서) {    // 오류 보고... } 또 다른 {    // 결과를 dlsym 호출에 사용합니다. } 

또는 프레임워크 또는 번들에 Objective-C 코드가 포함되어 있는 경우:

NS번들 *묶음 = [NS번들 번들 With Path:@"/라이브러리/플러그인/플러그인.번들"]; NSERror *에러 = 제로; 한다면 ([묶음 load And Return Error(로드 앤 리턴 에러):&에러]) {     // 번들 내의 클래스 및 함수를 사용합니다. } 또 다른 {     // 핸들 오류입니다. } 

창문들

모듈 sdl_module = 로드 라이브러리(본문("SDL.dll")); 한다면 (sdl_module == 특수한 순서) {    // 오류 보고... } 또 다른 {    // 결과를 GetProcAddress 호출에 사용합니다. } 

라이브러리 내용 추출 중

동적으로 로드된 라이브러리의 콘텐츠를 추출하려면GetProcAddressWindows 및 를 사용하여dlsymUNIX와 같은 운영체제에서 사용합니다.

UNIX 계열 운영체제(Solaris, Linux, *BSD, macOS 등)

무효* 이니셜라이저 = dlsym(sdl_module,"SDL_Init"); 한다면 (이니셜라이저 == 특수한 순서) {    // 오류 보고... } 또 다른 {    // 이니셜라이저를 적절한 타입으로 캐스트하여 사용 } 

macOS에서는 Objective-C 번들을 사용할 때 다음 작업도 수행할 수 있습니다.

학급 루트 클래스 = [묶음 프린서펄 클래스]; // 또는 NSClassFromString()을 사용하여 이름으로 클래스를 가져올 수도 있습니다. 한다면 (루트 클래스) {     아이디 물건 = [[루트 클래스 할당하다] 초기화]; // 개체를 사용합니다. } 또 다른 {     // 보고서 오류입니다. } 

창문들

FARPROC 이니셜라이저 = Get Proc Address(프로세서 주소)(sdl_module,"SDL_Init"); 한다면 (이니셜라이저 == 특수한 순서) {    // 오류 보고... } 또 다른 {    // 이니셜라이저를 적절한 타입으로 캐스트하여 사용 } 

라이브러리 함수 포인터 변환

의 결과dlsym()또는GetProcAddress()를 사용하려면 먼저 적절한 유형의 포인터로 변환해야 합니다.

창문들

Windows 에서는, FARPROC 는 기본적으로 이미 함수 포인터이기 때문에, 변환은 간단합니다.

유형화된 INT_PTR (*FARPROC)(무효); 

이는 함수가 아닌 객체의 주소를 취득할 때 문제가 될 수 있습니다.다만, 통상은 함수를 추출하고 싶기 때문에, 통상은 문제가 되지 않습니다.

유형화된 무효 (*sdl_init_function_type)(무효); sdl_init_function_type init_func = (sdl_init_function_type) 이니셜라이저; 

UNIX(POSIX)

POSIX 사양에 따르면,dlsym()는 입니다.void포인터단, 함수 포인터는 데이터 객체 포인터와 같은 크기일 필요는 없으며, 따라서 유형 간 변환이 유효합니다.void*또, 일부의 플랫폼에서는, 기능에의 포인터가 실장되기 어려운 경우가 있습니다.

오늘날 사용되는 대부분의 시스템에서 함수 및 객체 포인터는 사실 변환이 가능합니다.다음 코드 조각은 많은 시스템에서 변환을 수행할 수 있는 하나의 회피책을 보여 줍니다.

유형화된 무효 (*sdl_init_function_type)(무효); sdl_init_function_type init_func = (sdl_init_function_type)이니셜라이저; 

위의 스니펫은 일부 컴파일러에 대해 경고합니다.warning: dereferencing type-punned pointer will break strict-aliasing rules또 다른 회피책은 다음과 같습니다.

유형화된 무효 (*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호)에 대해서는 문제가 논의되었으며, 결론은 함수 포인터가 다음과 같이 변환되어야 한다는 것이었다.void*(POSIX 준거)[8]이를 위해서는 컴파일러 제조사가 이 케이스에 대해 작업 캐스트를 구현해야 합니다.

라이브러리의 내용을 변경할 수 있는 경우(예: 커스텀 라이브러리의 경우), 함수 자체 외에 라이브러리로의 포인터를 내보낼 수 있습니다.함수 포인터에 대한 포인터는 그 자체가 오브젝트 포인터이기 때문에 이 포인터는 항상 콜에 의해 합법적으로 취득할 수 있습니다.dlsym()및 후속 변환입니다.그러나 이 접근법은 외부에서 사용될 모든 기능에 대한 별도의 포인터를 유지해야 하며, 편익은 대개 작다.

라이브러리 언로드

라이브러리를 로드하면 메모리가 할당됩니다.메모리 누수를 방지하려면 라이브러리의 할당을 해제해야 합니다.또한 라이브러리를 언로드하지 못하면 라이브러리가 포함된 파일의 파일 시스템 작업이 방해될 수 있습니다.라이브러리의 언로드는 다음과 같이 행해집니다.FreeLibraryWindows 및 를 사용하여dlcloseUNIX와 같은 운영체제에서 사용합니다.다만, 메인 애플리케이션의 오브젝트가 DLL내에 할당된 메모리를 참조하고 있는 경우는, DLL 언로드에 의해서 프로그램의 크래시가 발생할 가능성이 있습니다.예를 들어 DLL에 새로운 클래스가 도입되어 DLL이 닫히면 메인애플리케이션에서 해당 클래스의 인스턴스를 더 조작하면 메모리액세스 위반이 발생할 가능성이 있습니다.마찬가지로 DLL이 동적으로 로드된 클래스를 인스턴스화하기 위한 공장 함수를 도입한 경우 DLL이 닫힌 후 기능하는 호출 또는 비회의는 정의되지 않은 동작으로 이어집니다.

UNIX 계열 운영체제(Solaris, Linux, *BSD, macOS 등)

닫다(sdl_module); 

창문들

프리 라이브러리(sdl_module); 

특수 라이브러리

UNIX와 유사한 운영 체제 및 Windows에서 동적 로딩의 구현을 통해 프로그래머는 현재 실행 중인 프로세스에서 기호를 추출할 수 있습니다.

UNIX와 유사한 운영체제는 프로그래머가 글로벌 심볼 테이블에 액세스할 수 있도록 합니다.이 테이블에는 메인 실행 파일과 이후 로드되는 동적 라이브러리가 모두 포함됩니다.

Windows 에서는, 프로그래머가 메인 실행 파일에 의해서 내보낸 심볼에 액세스 할 수 있습니다.Windows에서는 글로벌 심볼 테이블을 사용하지 않으며 이름으로 심볼을 찾기 위해 여러 모듈을 검색할 수 있는 API가 없습니다.

UNIX 계열 운영체제(Solaris, Linux, *BSD, macOS 등)

무효* this_프로세스 = 열리다(특수한 순서,0); 

창문들

모듈 this_프로세스 = Get Module 핸들(특수한 순서);  모듈 this_process_다시; Get Module HandleEx(0,0,&this_process_다시); 

자바어

Java 프로그래밍 언어에서는 객체를 사용하여 클래스를 동적으로 로드할 수 있습니다.예를 들어 다음과 같습니다.

학급 유형 = 클래스 로더.getSystemClassLoader().로드 클래스(이름.); 물건 obj = 유형.newInstance(); 

반사 메커니즘은 클래스를 아직 로드하지 않은 경우 해당 클래스를 로드하는 수단도 제공합니다.현재 클래스의 classloader를 사용합니다.

학급 유형 = 학급.이름(이름.); 물건 obj = 유형.newInstance(); 

그러나 제어된 방법으로 클래스를 언로드하는 간단한 방법은 없습니다.로드된 클래스는 제어된 방식으로만 언로드할 수 있습니다. 즉, 프로그래머가 이 작업을 수행할 때 클래스 로더가 시스템 클래스 로더가 아닌 경우, 시스템 클래스 로더 자체가 언로드됩니다.이 경우 클래스가 실제로 언로드되었는지 확인하기 위해 다양한 세부 사항을 관찰해야 합니다.이것은 수업의 하차를 지루하게 만든다.

Java에서는 가비지 컬렉터에 의한 제어되지 않은 방법으로 클래스의 암묵적인 언로드가 몇 번 변경되었습니다.Java 1.2까지는 가비지 컬렉터는 어떤 클래스 로더가 클래스를 로드하는 데 사용되었는지에 관계없이 공간이 필요하다고 느낄 때마다 클래스를 언로드할 수 있었습니다.시스템 클래스 로더를 통해 로드된 Java 1.2부터는 이 다른 클래스 로더가 언로드되었을 때만 다른 클래스 로더를 통해 로드된 클래스가 언로드되지 않았습니다.Java 6 클래스부터는 클래스 로드에 사용되는 클래스 로더와는 무관하게 가비지 컬렉터에 대해 언로드할 수 있음을 나타내는 내부 마커를 포함할 수 있습니다.컬렉터에 포함할 수 있습니다.가비지 컬렉터는 자유롭게 이 힌트를 무시할 수 있습니다.

마찬가지로 네이티브 메서드를 구현하는 라이브러리는 다음 명령어를 사용하여 동적으로 로드됩니다.System.loadLibrary방법.거기에는 없다System.unloadLibrary방법.

동적 부하가 없는 플랫폼

UNIX 및 Windows를 통해 1980년대에 보급되었지만 일부 시스템에서는 여전히 동적 로드를 추가 또는 제거하지 않았습니다.를 들어, Bell Labs의 Plan 9와 그 후계자인 9front는 동적인 링크를 의도적으로 회피하고 있습니다.동적인 링크는 「해롭다」[9]라고 생각되기 때문입니다.Plan 9와 동일한 개발자의 Go 프로그래밍 언어도 동적 링크를 지원하지 않았지만 Go 1.8(2017년 2월)부터 플러그인 로딩이 가능합니다.Go 런타임 및 라이브러리 함수는 컴파일된 [10]바이너리에 정적으로 링크됩니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ a b Autoconf, Automake 및 Libtool:동적 로드
  2. ^ "Linux4U: ELF Dynamic Loading". Archived from the original on 2011-03-11. Retrieved 2007-12-31.
  3. ^ "Using the CICS-supplied procedures to install application programs".
  4. ^ "IBM CEMT NEWCOPY or PHASEIN request fails with NOT FOR HOLD PROG - United States". 2013-03-15.
  5. ^ Ho, W. Wilson; Olsson, Ronald A. (1991). "An approach to genuine dynamic linking". Software: Practice and Experience. 21 (4): 375–390. CiteSeerX 10.1.1.37.933. doi:10.1002/spe.4380210404.
  6. ^ Apache 1.3 DSO(Dynamic Shared Object) 지원
  7. ^ GCC 4.3.2 최적화 옵션: -frict-aliasing
  8. ^ a b (문제 6 및 7)의 POSIX 매뉴얼
  9. ^ "Dynamic Linking". cat-v.org. 9front. Retrieved 2014-12-22.
  10. ^ "Go FAQ".

추가 정보

  • Silberschatz, Abraham; Galvin, Peter Baer; Gagne, Greg (2005). "Chapter 8.1.4 "Dynamic Loading" and Chapter 8.1.5 "Dynamic Linking and shared libraries"". Operating System Concepts. J. Wiley & Sons. ISBN 978-0-471-69466-3.

외부 링크