C/C++ 서로 다른 플랫폼에서 동적 연결은 어떻게 작동합니까?
동적 연결은 일반적으로 어떻게 작동합니까?
Windows(LoadLibrary)에서는 런타임에 호출하려면 .dll이 필요하지만 링크 시에는 해당하는 .lib 파일을 제공해야 합니다. 그렇지 않으면 프로그램이 링크되지 않습니다....lib 파일에는 무엇이 들어 있습니까?.dll 메서드에 대한 설명은?머리말에 그런 거 아니에요?
이와 관련해서 *nix에서는 lib 파일이 필요하지 않습니다.컴파일러는 헤더에 설명된 메소드를 런타임에 사용할 수 있는지 어떻게 알 수 있습니까?
초보자로서, 두 가지 계획 중 하나를 생각해보면, 다른 하나는, 둘 다 말이 안 됩니다.
질문에 하나씩 답하기
동적 연결은 연결 프로세스의 일부를 런타임으로 연기합니다.이것은 암시적으로 그리고 명시적으로 두 가지 방법으로 사용될 수 있습니다.암시적으로 정적 연결기는 실행 파일에 정보를 삽입하여 라이브러리가 필요한 기호를 로드하고 해결하도록 합니다.명시적으로 전화해야 합니다.
LoadLibrary아니면dlopen수동으로, 그리고 나서GetProcAddress/dlsym사용해야 할 각 기호에 대해 설명합니다.암묵적 로딩은 시스템 라이브러리와 같은 것에 사용되며, 구현은 시스템 버전에 따라 달라지지만 인터페이스는 보장됩니다.명시적 로딩은 플러그인과 같은 것에 사용되며, 여기서 로딩할 라이브러리는 런타임에 결정됩니다..lib파일은 암시적 로딩에만 필요합니다.라이브러리가 실제로 이 기호를 제공한다는 정보가 포함되어 있으므로 링커는 기호가 정의되지 않았다고 불평하지 않고, 링커가 어떤 라이브러리에 기호가 있는지 알려주기 때문에 필요한 정보를 삽입하여 이 라이브러리가 자동으로 로드되도록 할 수 있습니다.모든 헤더 파일이 컴파일러에게 알려주는 것은 기호들이 어딘가에 존재할 것이라는 것입니다; 링커는 다음을 필요로 합니다..lib어디에 있는지 알기 위해서 입니다.유닉스 하에서, 모든 정보는 다음으로부터 추출됩니다.
.so. Windows에서 모든 정보를 하나의 파일에 저장하는 것이 아니라 두 개의 개별 파일을 필요로 하는 이유는 모르겠지만, 대부분의 정보를 중복하고 있습니다..lib또한 필요합니다..dll일 것입니다 (아마도 라이센스 문제일 것입니다.프로그램을 배포할 수 있습니다..dll, 하지만 그들이 가지고 있지 않는 한 아무도 도서관들에 대항할 수 없습니다..lib.)
유지해야 할 주요 사항은 암시적 로딩을 원하는 경우 링커에 적절한 정보를 제공해야 한다는 것입니다..lib아니면..so실행 파일에 해당 정보를 삽입할 수 있습니다.명시적으로 로드하려면 라이브러리에 있는 기호를 직접 참조할 수 없습니다. 전화를 해야 합니다.GetProcAddress/dlsym그들의 주소를 직접 얻기 위해 (그리고 그것들을 사용하기 위해 재미있는 캐스팅을 하기 위해).
.lib동적 라이브러리를 로드하는 데 Windows의 파일이 필요한 것은 아니며, 단지 편리한 방법을 제공할 뿐입니다.
원칙적으로 dll을 로드하는 데 사용한 후GetProcAddress해당 dll에서 제공하는 함수에 액세스하기 위해.엔클로저 프로그램의 컴파일은 이 경우 dll에 액세스할 필요가 없으며 런타임(즉, 다음 경우)에만 필요합니다.LoadLibrary실제 실행).MSDN에는 코드 예시가 있습니다.
여기서 단점은 dll에서 함수를 로드하기 위해 수동으로 코드를 작성해야 한다는 것입니다.처음부터 직접 dll을 컴파일한 경우, 이 코드는 컴파일러가 dll 소스 코드에서 자동으로 추출할 수 있었던 지식(예: 내보낸 함수의 이름 및 서명)을 복제합니다.
이게 바로 그..lib파일은 다음을 수행합니다.포함되어 있습니다.GetProcAddress컴파일러에서 생성된 Dlls 내보내기 함수를 호출하므로 걱정할 필요가 없습니다.윈도우 용어로, 이것은 Load-Time Dynamic Linking이라고 불리는데, 엔클로저 프로그램이 로드될 때 Dll이 .lib 파일의 코드에 의해 자동으로 로드되기 때문입니다.
동적 연결은 일반적으로 어떻게 작동합니까?
동적 링크 라이브러리(일명 공유 객체) 파일에는 기계 코드 명령과 데이터가 포함되어 있으며, 해당 코드/데이터의 오프셋이 "기호", 기호 유형(예: 함수 대 데이터), 바이트 수 또는 데이터의 단어 수 등과 관련이 있다는 메타데이터 테이블도 포함되어 있습니다.OS마다 공유 객체 파일 형식이 다르며, 실제로 동일한 OS에서 여러 개를 지원할 수도 있지만, 그것이 핵심입니다.
그렇다면 공유 라이브러리가 다음과 같은 인덱스를 가진 바이트의 큰 덩어리라고 상상해 보십시오.
SYMBOL ADDRESS TYPE SIZE
my_function 1000 function 2893
my_number 4800 variable 4
일반적으로 메타데이터 테이블에 기호의 정확한 유형을 캡처할 필요는 없습니다. 라이브러리의 헤더 파일에 있는 선언에는 누락된 모든 정보가 포함되어 있어야 합니다.C++는 C와 비교하여 약간 특별합니다. 과부하는 같은 이름을 가진 함수가 여러 개 있다는 것을 의미할 수 있고 네임스페이스는 그렇지 않으면 모호하게 이름 붙여질 추가 기호를 허용하기 때문입니다. 이러한 이유로 네임 맹글링은 일반적으로 네임스페이스와 함수 인수의 일부 표현을 함수 이름에 연결하는 데 사용됩니다., 라이브러리 개체 파일에서 고유할 수 있는 것을 형성합니다.
공유 개체를 사용하려는 프로그램은 일반적으로 다음 두 가지 중 하나를 수행할 수 있습니다.
실행 전에 OS가 자신과 공유 객체를 동시에 로드하도록 합니다.
main()OS Loader가 기호를 찾아 프로그램 파일 이미지에서 해당 기호의 사용에 대한 메타데이터를 검사한 다음 프로그램이 사용하는 메모리의 기호 주소에 패치를 적용하는 역할을 맡으면서,그러면 프로그램이 처음 컴파일되었을 때 심볼 주소에 대해 알고 있었던 것처럼 기능적으로 실행되고 작동할 수 있습니다(그러나 아마 조금 느릴 수도 있습니다).또는, 명시적으로 자체 소스 코드 호출에 있습니다.
dlopen얼마 후에main실행, 사용dlsym또는 이와 유사하게 기호 주소를 가져오려면 예상 데이터 유형에 대한 프로그래머의 지식에 따라 (함수/데이터) 포인터에 저장한 다음 포인터를 사용하여 명시적으로 호출합니다.
Windows(LoadLibrary)에서는 런타임에 호출하려면 .dll이 필요하지만 링크 시에는 해당하는 .lib 파일을 제공해야 합니다. 그렇지 않으면 프로그램이 링크되지 않습니다...
그것은 옳지 않은 것 같습니다.내 생각엔 둘 중 하나가 되어야 할 것 같아요.
.lib 파일에 포함된 내용은 무엇입니까?.dll 메서드에 대한 설명은?머리말에 그런 거 아니에요?
lib 파일은 - 이 설명 수준에서 - 공유 객체 파일과 거의 같습니다...가장 큰 차이점은 컴파일러가 프로그램이 전송되고 실행되기 전에 심볼 주소를 찾는다는 것입니다.
현대 *nix 시스템은 Solaris OS에서 동적 링크 프로세스를 도출합니다.특히 리눅스는 모든 외부 종속성이 ELF 형식으로 포함되어 있기 때문에 별도의 .lib 파일이 필요하지 않습니다..interpELF 파일의 섹션은 이 실행 파일 내부에 동적으로 해결해야 할 외부 기호가 있음을 나타냅니다.이것은 동적 링크를 위해 제공됩니다.
사용자 공간에서 동적 링크를 처리하는 방법이 있습니다.이 방법을 동적 로딩이라고 합니다.시스템 호출을 사용하여 외부 *.so에서 메서드에 대한 함수 포인터를 가져오는 경우입니다.
자세한 내용은 이 기사 http://www.ibm.com/developerworks/library/l-dynamic-libraries/ 에서 확인할 수 있습니다.
관련해서, OS X에서 (그리고 *nix를 가정합니다...dlopen), lib 파일은 필요없습니다...컴파일러는 헤더에 설명된 메소드를 런타임에 사용할 수 있는지 어떻게 알 수 있습니까?
컴파일러나 링커는 이러한 정보를 필요로 하지 않습니다.프로그래머인 당신은 당신이 열려는 공유 라이브러리들이dlopen()존재하지 않을 수 있습니다.
윈도우즈에서 DLL 파일은 다음과 같은 두 가지 방법으로 사용할 수 있습니다.링크를 걸면 끝이고, 더 이상 할 일이 없어집니다.또는 런타임 중에 동적으로 로드합니다.
링크하면 DLL 라이브러리 파일이 사용됩니다.링크 라이브러리에는 링크러가 로드할 DLL과 DLL 함수의 위치를 실제로 알기 위해 사용하는 정보가 포함되어 있으므로 이를 호출할 수 있습니다.프로그램이 로드되면 운영 체제에서도 DLL을 로드합니다. 기본적으로 이름은 무엇입니까?LoadLibrary널 위해서.
OS X나 리눅스와 같은 다른 운영 체제에서도 비슷한 방식으로 작동합니다.차이점은 이러한 시스템에서 링커가 동적 라이브러리를 직접 볼 수 있다는 것입니다..so/.dynlib파일) 및 Windows에서와 같은 별도의 정적 라이브러리 없이 필요한 것을 파악할 수 있습니다.
라이브러리를 동적으로 로드하려면 로드할 라이브러리와 관련된 어떤 것과도 연결할 필요가 없습니다.
다른 사람들이 이미 말한 것처럼: a에 포함된 것.lib윈도우의 파일은 직접적으로 포함됩니다..so/.dynlib리눅스/OS X에서 말입니다. 하지만 중요한 질문은... 왜일까요?*nix 솔루션이 더 좋지 않습니까?제 생각에는 그렇지만..lib한 가지 장점이 있습니다.DLL에 링크하는 개발자는 실제로 DLL 파일 자체에 액세스할 필요가 없습니다.
그런 시나리오가 현실에서 자주 일어나나요?DLL 파일 하나에 두 개의 파일을 유지하는 노력이 가치가 있습니까?몰라.
편집: 좋아요, 여러분, 상황을 더 혼란스럽게 만들어 봅시다!MinGW를 사용하여 Windows의 DLL에 직접 연결할 수 있습니다.따라서 전체 가져오기 라이브러리 문제는 Windows 자체와 직접적인 관련이 없습니다.MinGW wiki의 샘플 DLL 기사에서 가져온 것:
DLL이 MinGW 툴체인이 아닌 다른 일부 C/C++ 컴파일러에서 인터페이싱되어야 하는 경우 "--out-implib" linker 옵션에 의해 생성된 Import library가 필요합니다.MinGW 툴체인은 생성된 DLL을 직접 링크할 수 있어 매우 기쁩니다.자세한 내용은 binutils 패키지의 일부인 ld.exe info 파일(툴 체인의 일부인)에서 확인할 수 있습니다.
리눅스는 또한 링크를 요구하지만 대신에 를 반대합니다.Lib 라이브러리는 동적 연결기에 연결해야 합니다./lib/ld-linux.so.2, 그러나 이는 일반적으로 GCC를 사용할 때 뒤에서 발생합니다(그러나 어셈블러를 사용할 경우 수동으로 지정해야 함).
둘 다 접근합니다. 윈도우.LIB 접근법 또는 리눅스 동적 링커 연결 접근법은 실제로 정적 링크로 간주됩니다.그러나 Windows에서는 로드 시간에 작업이 남아 있지만 링크 시간에 작업이 수행된다는 차이점이 있습니다(잘은 모르겠지만).LIB 파일은 링커가 물리적 라이브러리 이름을 알기 위한 것일 뿐이지만 심볼은 로드 시에만 해결됩니다). 리눅스에서는 동적 링커로의 링크 이외의 모든 것이 로드 시에 발생합니다.
동적 링크는 일반적으로 런타임에 DLL 파일을 수동으로 여는 것을 말합니다(예: LoadLinary()). 이 경우 부담은 전적으로 프로그래머에게 있습니다.
공유 라이브러리(예:.dll .dylib그리고..so, 기호의 이름과 주소에 대한 정보는 다음과 같습니다.
------------------------------------
| symbol's name | symbol's address |
|----------------------------------|
| Foo | 0x12341234 |
| Bar | 0xabcdabcd |
------------------------------------
그리고 부하 함수, 예를 들어LoadLibrary그리고.dlopen, 공유 라이브러리를 로드하고 사용할 수 있도록 합니다.
GetProcAddress그리고.dlsym기호의 주소를 찾습니다.예를 들어,
HMODULE shared_lib = LoadLibrary("asdf.dll");
void *symbol = GetProcAddress("Foo");
// symbol is 0x12341234
에는이 ..lib사용할 파일.dll. 이 링크를 클릭합니다..lib파일, 전화할 필요는 없습니다.LoadLibrary그리고.GetProcAddress, 공유 라이브러리의 기능을 "정상적인" 기능인 것처럼 사용할 수 있습니다.어떻게 되는 거지?
은..lib에는 가져오기 정보가 들어 있습니다.이런 거죠.
void *Foo; // please put the address of Foo there
void *Bar; // please put the address of Bar there
운영 체제가 프로그램(엄밀하게 말하면 모듈)을 로드할 때 운영 체제는 다음을 수행합니다.LoadLibrary그리고.GetProcAddress자동으로.
그리고 만약 당신이 다음과 같은 코드를 쓴다면.Foo();, 컴파일러로 변환합니다.(*Foo)();자동으로. 마치 정상적인 기능인 것처럼 사용할 수 있습니다따라서 마치 "정상" 기능인 것처럼 사용할 수 있습니다.
언급URL : https://stackoverflow.com/questions/22860577/c-c-how-does-dynamic-linking-work-on-different-platforms
'programing' 카테고리의 다른 글
| ar의 "rcs" 옵션은 무엇을 합니까? (0) | 2023.10.30 |
|---|---|
| PL/SQL 전용 VARCHAR232767 바이트를 모두 만들지 않는 이유는 무엇입니까? (0) | 2023.10.30 |
| char보다 큰 정수를 받아들이는 memset()이 있습니까? (0) | 2023.10.30 |
| AngularJS에서 배열이 아닌 개체 맵에서 필터링 (0) | 2023.10.25 |
| $.param을 angularjs로 변환 (0) | 2023.10.25 |