동적 연결-Linux Vs. 윈도우


10

Windows에서 MSVC의 DLL 프로젝트에서 C / C ++ 코드를 컴파일하면 2 개의 파일이 나타납니다.

  1. MyDll.dll
  2. MyDll.lib

내가 이해 MyDll.lib하는 한 dll의 함수 위치를 나타내는 일종의 포인터 테이블이 포함되어 있습니다. 이 dll (예 : exe 파일) MyDll.lib을 사용하면 링크하는 동안 exe 파일에 포함되므로 런타임시 함수가있는 위치를 "알고" MyDll.dll사용할 수 있습니다.

그러나 Linux에서 동일한 코드를 컴파일하면 ( Linux의 파일 과 동등한) 파일이 없는 하나의 파일 만 가져 옵니다 . 리눅스의 실행 파일 은 링크하는 동안 아무것도 포함되어 있지 않으면 함수의 위치를 어떻게 알 수 있습니까?MySo.soMySo.alibMySo.so

답변:


1

Linux에서 링커 (동적 링커 아님)는 링크 타임에 지정된 공유 라이브러리를 검색하여 실행 파일 내에 해당 라이브러리에 대한 참조를 작성합니다. 동적 링커는 이러한 실행 파일을로드 할 때 필요한 공유 라이브러리를 메모리에로드하고 심볼을 확인하여 바이너리를 실행할 수있게합니다.

MySo.a생성 된 경우 실제로는 Windows에서 사용되는 "기호 찾아보기 테이블"대신 이진에 직접 링크 될 기호가 포함됩니다.

rustyx의 답변 은 Windows의 프로세스를 내가 할 수있는 것보다 더 철저하게 설명합니다. Windows를 사용한 지 오래되었습니다.


1
"Windows는 다른 접근 방식을 취합니다 ... 기호가 DLL에있는 정확한 위치에 운영 체제를 지정하십시오."- 위키 와 모순됩니다. 즉, 시작시 또는 라이브러리 함수를 처음 호출 할 때 함수 이름이 여전히 해결된다고합니다. 서수 사용 (라이브러리 사용자가 라이브러리가 변경 될 때마다 코드를 다시 컴파일하고 재배치하도록 강요하기 때문에 직접 주소 바인딩을 사용하지 않는 한)
yugr

@yugr 그 부분을 제거하고 어쨌든 빨대를 잡고있었습니다.
SS Anne

4

MSVC 링커는 개체 파일 (.obj)과 개체 라이브러리 (.lib)를 함께 연결하여 .EXE 또는 .DLL을 생성 할 수 있습니다.

DLL과 연결하기 위해 MSVC의 프로세스는 C 함수 이름과 DLL의 익스포트 테이블 (DLL에서 함수를 이름 또는 에 의해 순서 - 후자는 종종) 문서화되지 않은 API를 사용 하였다.

그러나 대부분의 경우 DLL 내보내기 테이블에는 모든 함수 이름이 있으므로 가져 오기 라이브러리 (.LIB)에는 중복 정보가 많이 포함됩니다 ( " 가져 오기 기능 ABC-> 내 보낸 기능 ABC "등). 기존 .DLL에서 .LIB
생성 할 수도 있습니다 .

다른 플랫폼의 링커에는 이러한 "기능"이 없으며 동적 라이브러리와 직접 연결할 수 있습니다.


"다른 플랫폼의 링커에는이 기능이 없습니다."- 지연된로드 및 기타 기능을 달성 하기 위해 구현하기 쉽습니다 (예 : Linux의 경우 Implib.so 가이를 수행함 ).
yugr

@yugr : 그렇기 때문에 "feature"가 따옴표로 묶여 있습니다. 일반적으로하고 싶은 것이 아니며 Windows에서해야 할 추가 작업입니다.
Chris Dodd

1

차이점은 구현 세부 사항입니다. 리눅스와 Windows 모두 비슷하게 작동합니다. 코드는 실행 파일에 정적으로 링크 된 스텁 함수를 호출 하고이 스텁은 필요한 경우 DLL / shlib를로드합니다 ( 지연된 경우) loading , 그렇지 않으면 프로그램이 시작될 때 라이브러리가로드되고 (첫 번째 호출시) GetProcAddress/ 를 통해 심볼을 확인합니다 dlsym.

유일한 차이점은 Linux에서 응용 프로그램을 동적 라이브러리 (라이브러리에 생성하기에 충분한 정보가 포함되어 있음)와 링크 할 때 이러한 스텁 함수 (PLT 스텁이라고 함)가 동적으로 생성되는 반면, Linux에서는 DLL 자체가 별도의 .lib파일로 생성 됩니다.

두 가지 접근 방식은 매우 유사하여 실제로 Linux에서 Windows 가져 오기 라이브러리를 모방 할 수 있습니다 ( Implib.so 프로젝트 참조 ).


0

Linux MySo.so에서 링커에 전달 하면 링크 단계에 필요한 항목 만 추출 MySo.so하여 런타임에 필요한 참조를 넣을 수 있습니다.


-3

.dll또는 .so공유 라이브러리 (런타임에 링크 됨).a.lib정적 라이브러리 (컴파일 시간에 연결이)입니다. 이것은 Windows와 Linux의 차이가 아닙니다.

차이점은 처리 방법입니다. 참고 : 차이점은 세관에만 있으며, 어떻게 사용됩니까? 실제로 아무도이 작업을 수행하지 않는다는 점을 제외하고 Windows를 Linux 방식으로 빌드하는 것은 그다지 어렵지 않습니다.

dll을 사용하거나 자체 바이너리에서도 함수를 호출하면 간단하고 명확한 방법이 있습니다. 예를 들어 C에서 우리는 다음을 볼 수 있습니다.

int example(int x) {
  ...do_something...
}

int ret = example(42);

그러나 asm 수준에서는 많은 차이가있을 수 있습니다. 예를 들어, x86에서 callopcode가 실행되고 42스택에 제공됩니다. 또는 일부 레지스터에서. 아니면 어디서나. dll을 작성하기 전에 아무도 그것을 모른다 어떻게 사용되는지 알 수 없습니다. 또는 프로젝트가 어떻게 그것을 사용하기를 원하는지, 현재 존재하지 않는 컴파일러 (또는 언어로 작성)로 작성 가능하거나 dll 개발자에게는 알려지지 않았습니다.

예를 들어, 기본적으로 C와 Pascal은 모두 스택에서 인수를 가져오고 반환 값을 가져옵니다. 그러나 서로 다른 순서로 수행합니다 . 컴파일러에 따라 최적화하여 레지스터의 함수간에 인수를 교환 할 수도 있습니다.

올바르게 볼 때, 윈도우 사용자는 DLL을 구축하여, 우리는 또한 최소한의를 만들 수 있다는 것입니다 .a/.lib 그것입니다. 이 최소 정적 라이브러리는 래퍼 일 뿐이며 해당 DLL의 기호 (기능)는이를 통해 도달합니다. 필요한 asm 수준의 통화 변환이 이루어집니다.

장점은 호환성입니다. 단점은 .dll 만 있으면 해당 함수를 호출하는 방법을 알아내는 데 어려움을 겪을 수 있다는 것입니다. dll 개발자가 당신에게을 제공하지 않으면 dll.a 사용법을 해킹 작업으로 만듭니다 . 따라서 주로 폐쇄 목적으로 사용되므로 SDK에 대한 추가 현금을 얻는 것이 더 쉽습니다.

또 다른 단점은 동적 라이브러리를 사용하더라도이 작은 래퍼를 정적으로 컴파일해야한다는 것입니다.

Linux에서 dll의 이진 인터페이스는 표준이며 C 규칙을 따릅니다. 따라서 .a공유 라이브러리간에 이진 호환성이 필요하지 않으며 Microsoft 사용자 지정의 이점이 없습니다.


1
스텁 함수가 인수 순서를 변경할 수있는 교정 링크를 제공하십시오. 나는 전에 이것에 대해 들어 본 적이 없으며 성능 오버 헤드가 얼마나 클지 믿기 어렵습니다.
yugr

@yugr 간단한 레지스터 / 스택 재정렬은 성능 오버 헤드가 아닙니다. msvc 컴파일 바이너리에서 msvc 컴파일 dll을 사용하면 너무 많이 발생하지는 않지만 분명히 발생할 수 있습니다.
peterh-Reinstate Monica

1
우리는 이것에 대해 논쟁 할 수는 있지만 당신이 옳다면 스텁 함수가 사소한 인수를 처리 할 수 ​​있다는 증거 링크를 제공하는 것이 쉬워야합니다 (그리고 단순한 트램폴린 이상).
yugr

@yugr 스텁은 dll의 함수 서명에 액세스하여 사소한 처리를 간단하게 만듭니다.
peterh-Reinstate Monica

1
가져 오기 라이브러리의 기능에 대한 몇 가지 교정 링크로 답변을 완성하는 것이 좋습니다 (일부 주장에 의문이 있기 때문에).
yugr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.