Programing

공유 객체 (.so), 정적 라이브러리 (.a) 및 DLL (.so)의 차이점은 무엇입니까?

lottogame 2020. 4. 5. 19:53
반응형

공유 객체 (.so), 정적 라이브러리 (.a) 및 DLL (.so)의 차이점은 무엇입니까?


나는 리눅스 라이브러리와 관련하여 토론에 참여했으며, 몇 가지 사항을 확인하고 싶습니다.

응용 프로그램을 만들 때 라이브러리를 사용하는 두 가지 방법이 있다는 것이 내 이해 (잘못되면 수정하고 나중에 게시물을 편집 할 것입니다)입니다.

  1. 정적 라이브러리 (.a 파일) : 링크 타임에 전체 라이브러리의 복사본이 최종 응용 프로그램에 저장되므로 라이브러리 내의 함수를 항상 호출 응용 프로그램에서 사용할 수 있습니다
  2. 공유 객체 (.so 파일) : 링크 타임에 객체는 해당 헤더 (.h) 파일을 통해 API에 대해 확인됩니다. 라이브러리는 실제로 필요할 때까지 런타임까지 사용되지 않습니다.

정적 라이브러리의 명백한 장점은 전체 응용 프로그램을 자체적으로 포함 할 수 있다는 것과 동적 라이브러리의 장점은 ".so"파일을 대체 할 수 있다는 것입니다 (예 : 보안으로 인해 업데이트해야하는 경우) 기본 응용 프로그램을 다시 컴파일하지 않아도됩니다.

공유 객체와 DLL (동적 연결 라이브러리)이 ".so"파일 인 경우에도 일부 사람들이 구별한다고 들었습니다. Linux 또는 기타 POSIX 호환 OS (예 : MINIX, UNIX, QNX 등)에서 C / C ++ 개발에있어 공유 객체와 DLL 사이에 차이점이 있습니까? 지금까지 한 가지 중요한 차이점은 공유 객체가 런타임에 방금 사용되는 반면 DLL은 응용 프로그램 내에서 dlopen () 호출을 사용하여 먼저 열어야한다는 것입니다.

마지막으로, 일부 개발자는 "공유 아카이브"를 언급하는 것을 들었습니다.이 라이브러리는 이해하기에는 정적 라이브러리이지만 응용 프로그램에서 직접 사용하지는 않습니다. 대신, 다른 정적 라이브러리는 "공유 아카이브"와 연결되어 공유 아카이브에서 일부 (전부는 아님) 기능 / 자원을 빌드중인 정적 라이브러리로 가져옵니다.

도움을 주셔서 감사합니다.

최신 정보


이 용어가 제게 제공된 상황에서, Linux를 배워야하는 Windows 개발자 팀이 사용하는 용어는 사실상 잘못된 용어였습니다. 나는 그들을 고치려고 노력했지만 (잘못된) 언어 규범이 고착되었다.

  1. 공유 객체 : 프로그램이 시작될 때 프로그램에 자동으로 연결되고 독립형 파일로 존재하는 라이브러리입니다. 라이브러리는 컴파일 타임에 링크 목록에 포함됩니다 (예 : LDOPTS+=-lmylib라는 라이브러리 파일의 경우 mylib.so). 라이브러리는 컴파일 타임과 응용 프로그램이 시작될 때 있어야합니다.
  2. 정적 라이브러리 : 응용 프로그램 코드와 프로그램이 빌드 될 때 프로그램에 자동으로 링크되는 라이브러리 코드 및 둘 다를 포함하는 최종 바이너리를 포함하는 단일 (큰) 응용 프로그램의 빌드 시간에 실제 프로그램 자체에 병합되는 라이브러리 기본 프로그램과 라이브러리 자체는 단일 독립 실행 형 이진 파일로 존재합니다. 라이브러리는 컴파일 타임에 링크 목록에 포함됩니다 (예 : LDOPTS+=-lmylibmylib.a라는 라이브러리 파일의 경우). 라이브러리는 컴파일 타임에 존재해야합니다.
  3. DLL : 기본적으로 공유 객체와 동일하지만 컴파일 타임에 링크 목록에 포함되지 않고 라이브러리는 dlopen()/ dlsym()명령을 통해로드 되므로 프로그램을 컴파일하기 위해 빌드시 라이브러리가 없어도됩니다. 또한 라이브러리는 응용 프로그램을 시작하거나 컴파일 할 때 (필수적으로) 존재할 필요가 없습니다 . 왜냐하면 dlopen/ dlsym호출이 수행 되는 순간에만 필요하기 때문입니다 .
  4. 공유 아카이브 : 기본적으로 정적 라이브러리와 동일하지만 "내보내기 공유"및 "-fPIC"플래그로 컴파일됩니다. 라이브러리는 컴파일 타임에 링크 목록에 포함됩니다 (예 : LDOPTS+=-lmylibS라는 라이브러리 파일의 경우 mylibS.a). 이 둘의 차이점은 공유 객체 또는 DLL이 공유 아카이브를 자체 코드에 정적으로 링크하고 공유 객체의 기능을 다른 프로그램에서 사용할 수있게 만들려는 경우이 추가 플래그가 필요하다는 것입니다. DLL 내부. 이것은 누군가가 정적 라이브러리를 제공하고이를 SO로 다시 패키지하려는 경우에 유용합니다. 라이브러리는 컴파일 타임에 존재해야합니다.

추가 업데이트

" DLL"와 " shared library" 의 구분은 위에서 언급 한 설명을 준수하면서 당시 내가 일했던 회사 (Windows 개발자는 Linux 개발로 강제 이동하고 강제라는 용어)에서 (게으르고, 부정확 한) 구어체 일뿐이었습니다.

또한 S"공유 아카이브"의 경우 라이브러리 이름 다음에 나오는 " "리터럴은 해당 업계에서 일반적으로 사용되는 것이 아니라 해당 회사에서 사용 된 규칙 일뿐입니다.


나는 항상 DLL과 공유 객체가 같은 것에 대해 다른 용어라고 생각했습니다 .Windows는 DLL을 DLL이라고 부릅니다 .UNIX 시스템에서는 공통 용어 인 동적으로 연결된 라이브러리와 함께 공유 객체입니다. UNIX에서 .so를 열면 dlopen()'동적 라이브러리' 라고 불립니다 .

그것들은 실제로 응용 프로그램 시작시에만 연결되지만 헤더 파일에 대한 검증 개념은 올바르지 않습니다. 헤더 파일은 라이브러리를 사용하는 코드를 컴파일하는 데 필요한 프로토 타입을 정의하지만 링크 타임에 링커는 라이브러리 자체를 조사하여 필요한 기능이 실제로 있는지 확인합니다. 링커는 링크 타임에 함수 본문을 찾아야합니다. 그렇지 않으면 오류가 발생합니다. 프로그램이 컴파일 된 후 라이브러리 자체가 변경되었을 수도 있기 때문에 런타임에도 마찬가지입니다. 이것이 플랫폼 라이브러리에서 ABI 안정성이 중요한 이유입니다. ABI 변경으로 인해 기존 프로그램이 이전 버전에 대해 컴파일 된 것이기 때문입니다.

정적 라이브러리는 프로젝트 컴파일의 일부로 자신을 빌드하는 것과 마찬가지로 컴파일러에서 직접 객체 파일 묶음이므로 정확히 같은 방식으로 링커에 가져와 공급되며 사용되지 않는 비트는 정확히 같은 방식으로 떨어졌습니다.


정적 라이브러리 (.A)는 링커에 의해 생성 된 최종 실행에 직접 연결할 수있는 도서관, 그것은 그 안에 포함되고 실행 파일이 배포 될 시스템에 라이브러리가 할 필요가 없습니다.

공유 라이브러리 (.so를) 실행 파일이 실행되고 필요는 실행 파일이 배포 된 시스템에 존재하는 경우에 너무로드됩니다 연결된하지만 최종 실행 파일에 포함되지 않은 라이브러리입니다.

windows (.dll)동적 링크 라이브러리 는 Linux의 공유 라이브러리 (.so)와 비슷하지만 OS (Windows와 Linux)와 관련된 두 구현 사이에는 약간의 차이가 있습니다.

DLL은 두 가지 종류의 함수를 정의 할 수 있습니다 : 수출 및 내부. 내 보낸 함수는 정의 된 DLL 내 에서뿐만 아니라 다른 모듈에서도 호출하도록되어 있습니다. 내부 함수는 일반적으로 정의 된 DLL 내에서만 호출하도록되어 있습니다.

Linux SO 라이브러리는 모든 심볼을 심문 프로세스에 사용할 수 있으므로 내보낼 수있는 심볼을 나타 내기 위해 특별한 내보내기 명령문이 필요하지 않습니다.


Windows의 DLL 세부 정보를 자세히 설명하여 여기 * NIX-land에서 내 친구들에게 그 신비를 명확히 할 수 있습니다.

DLL은 공유 객체 파일과 같습니다. 둘 다 이미지이며, 해당 OS의 프로그램 로더가 메모리에로드 할 수 있습니다. 이미지에는 링커와 로더가 필요한 연결을 만들고 코드 라이브러리를 사용하는 데 도움이되는 다양한 메타 데이터가 함께 제공됩니다.

Windows DLL에는 내보내기 테이블이 있습니다. 내보내기는 이름 또는 테이블 위치 (숫자)별로 수행 될 수 있습니다. 후자의 방법은 "오래된 학교"로 간주되며 훨씬 더 취약합니다. DLL을 다시 작성하고 테이블에서 함수의 위치를 ​​변경하면 재난으로 끝날 것입니다. 반면 진입 점 연결이 이름으로되어 있으면 실제 문제는 없습니다. 따라서 문제로 잊어 버리십시오. 그러나 타사 공급 업체 라이브러리와 같은 "공룡"코드로 작업하는 경우 문제가 있음을 명심하십시오.

Windows DLL은 EXE (실행 가능 응용 프로그램)와 마찬가지로 컴파일 및 링크로 작성되지만 동적로드 또는 응용 프로그램에서 SO를 사용하는 것처럼 DLL은 단독으로 사용되지 않아야합니다. 링크 타임 바인딩 (SO에 대한 참조는 응용 프로그램 바이너리의 메타 데이터에 포함되어 있으며 OS 프로그램 로더는 참조 된 SO를 자동로드합니다). SO가 다른 SO를 참조 할 수있는 것처럼 DLL은 다른 DLL을 참조 할 수 있습니다.

Windows에서 DLL은 특정 진입 점 만 사용할 수있게합니다. 이를 "수출"이라고합니다. 개발자는 특수 컴파일러 키워드를 사용하여 심볼을 외부에서 볼 수 있도록 (다른 링커 및 동적 로더에 표시) 만들거나 DLL 자체가있을 때 링크 타임에 사용되는 모듈 정의 파일에 내보내기를 나열 할 수 있습니다. 작성 중입니다. 현대적인 방법은 키워드로 함수 정의를 장식하여 심볼 이름을 내보내는 것입니다. 키워드를 사용하여 현재 컴파일 단위 외부의 DLL에서 가져올 기호로 선언하는 헤더 파일을 만들 수도 있습니다. 자세한 내용은 키워드 __declspec (dllexport) 및 __declspec (dllimport)을 찾으십시오.

DLL의 흥미로운 기능 중 하나는 표준 "로드시 / 언로드"핸들러 함수를 선언 할 수 있다는 것입니다. DLL이로드되거나 언로드 될 때마다 DLL은 경우에 따라 초기화 또는 정리를 수행 할 수 있습니다. 이것은 DLL을 장치 드라이버 또는 공유 객체 인터페이스와 같은 객체 지향 자원 관리자로 사용하는 데 적합합니다.

개발자가 이미 구축 된 DLL을 사용하려면 DLL을 만들 때 DLL 개발자가 만든 "내보내기 라이브러리"(* .LIB)를 참조하거나 런타임에 DLL을 명시 적으로로드하고 요청해야합니다. LoadLibrary () 및 GetProcAddress () 메커니즘을 통한 이름 별 진입 점 주소 대부분의 경우 DLL이 내 보낸 진입 점에 대한 링커 메타 데이터를 포함하는 LIB 파일에 대한 링크는 DLL이 사용되는 방식입니다. 동적 로딩은 일반적으로 프로그램 동작 (추가 기능 또는 나중에 정의 된 기능, 즉 "플러그인"에 액세스)에서 "다형성"또는 "런타임 구성"을 구현하기 위해 예약되어 있습니다.

Windows 작업 방식은 때때로 혼란을 야기 할 수 있습니다. 시스템은 .LIB 확장자를 사용하여 일반 정적 라이브러리 (POSIX * .a 파일과 같은 아카이브)와 링크 타임에 응용 프로그램을 DLL에 바인딩하는 데 필요한 "내보내기 스텁"라이브러리를 모두 참조합니다. 따라서 * .LIB 파일에 같은 이름의 * .DLL 파일이 있는지 항상 확인해야합니다. 그렇지 않으면 * .LIB 파일이 정적 라이브러리 아카이브이고 DLL의 바인딩 메타 데이터를 내 보내지 않을 가능성이 높습니다.


정적 파일은 링크 타임에 응용 프로그램에 복사되고 공유 파일은 링크 타임에 확인되고 런타임에로드됩니다.

dlopen 호출은 공유 객체에 대한 것이 아니라 응용 프로그램이 런타임에 그렇게하려는 경우 응용 프로그램이 시작될 때 공유 객체가 자동으로로드됩니다. DLLS와 .so는 동일합니다. dlopen은 프로세스에보다 세분화 된 동적 로딩 기능을 추가하기 위해 존재합니다. DLL을 열거 나 사용하기 위해 dlopen을 직접 사용할 필요는 없으며 응용 프로그램 시작시에도 발생합니다.

참고 URL : https://stackoverflow.com/questions/9688200/difference-between-shared-objects-so-static-libraries-a-and-dlls-so

반응형