공유 개체(.so), 정적 라이브러리(.a) 및 DLL(.so) 간의 차이점?
나는 Linux에 있는 도서관과 관련하여 토론에 참여했고, 몇 가지 사항을 확인하고 싶다.
응용프로그램을 작성할 때 라이브러리를 사용하는 방법은 다음과 같은 두 가지 방법(잘못된 경우 수정해 주시고 나중에 게시물을 편집하겠다)으로 나는 이해한다.
- 정적 라이브러리(.a 파일):링크 시간에, 도서관 내의 기능들이 항상 호출 어플리케이션에 이용될 수 있도록 최종 어플리케이션에 전체 라이브러리의 복사본을 넣는다.
- 공유 개체(.so 파일):링크 시간에 객체는 해당 헤더(.h) 파일을 통해 API에 대해 확인된다.도서관은 실제로 필요한 곳인 런타임까지 이용되지 않는다.
정적 라이브러리의 분명한 이점은 응용 프로그램 전체를 자급자족할 수 있도록 하는 반면, 동적 라이브러리의 이점은 기본 응용 프로그램을 다시 컴파일할 필요 없이 ".so" 파일을 교체할 수 있다는 것이다(즉, 보안 버그로 인해 업데이트가 필요한 경우).
일부 사람들은 공유 개체와 동적 링크 라이브러리(DLLs)를 구별한다고 들었는데, 둘 다 ".so" 파일임에도 불구하고 말이다.리눅스에서의 C/C++ 개발이나 다른 POSIX 호환 OS(예: MINIX, UNIX, QNX 등)에 관해서는 공유 개체와 DLL의 구분이 있는가?한 가지 중요한 차이점(현재까지)은 공유 객체가 런타임에 그냥 사용되는 반면 DLL은 애플리케이션 내에서 dlopen() 호출을 사용하여 먼저 열어야 한다는 점을 들었다.
마지막으로, 나는 또한 일부 개발자들이 "공유된 보관소"를 언급하는 것을 들었다. 이 보관소 또한 내가 이해하기로는 정적 도서관 그 자체이지만 응용 프로그램에서 직접 사용하지 않는다.대신 다른 정적 라이브러리는 공유 아카이브에서 일부 기능/리소스를 빌드 중인 정적 라이브러리로 끌어오기 위해 "공유된 아카이브"에 대해 링크할 것이다.
너의 도움에 미리 모두 고마워.
갱신하다
이러한 용어들이 나에게 제공된 맥락에서, 그것은 사실상 리눅스를 배워야 했던 윈도우 개발자들에 의해 사용된 잘못된 용어였다.고치려고 했지만 (잘못된) 언어 규범이 고착되었다.
- 공유 개체:프로그램이 시작될 때 프로그램에 자동으로 연결되어 독립 실행형 파일로 존재하는 라이브러리.라이브러리는 컴파일 시 링크 목록에 포함된다(즉:
LDOPTS+=-lmylib
이름을 가진 라이브러리 파일의 경우mylib.so
( ) 라이브러리는 컴파일 시간과 애플리케이션이 시작될 때 존재해야 한다. - 정적 라이브러리: 응용 프로그램 코드와 프로그램이 구축될 때 프로그램에 자동으로 연결되는 라이브러리 코드를 포함하는 단일(더 많은) 응용 프로그램의 빌드 시간에 실제 프로그램 자체에 병합되는 라이브러리로서, 메인 프로그램과 라이브러리 자체를 모두 포함하는 최종 바이너리가 단일 독립 실행형으로 존재한다.이진 파일.라이브러리는 컴파일 시 링크 목록에 포함된다(즉:
LDOPTS+=-lmylib
이름을 가진 라이브러리 파일의 경우mylib.a
( ) 도서관은 컴파일 시간에 존재해야 한다. - DLL: 기본적으로 공유 개체와 동일하지만 컴파일 시 링크 목록에 포함되지 않고 라이브러리를 통해 로드됨
dlopen()
/dlsym()
프로그램을 컴파일하기 위해 빌드 시간에 라이브러리가 있을 필요가 없도록 명령한다.또한, 도서관은 현재에만 필요하므로, 애플리케이션 시작이나 컴파일 시간에 (필요하게) 존재할 필요가 없다.dlopen
/dlsym
전화가 걸려오다 - 공유 아카이브: 기본적으로 정적 라이브러리와 동일하지만 "export-shared" 및 "inport-shared"로 컴파일됨
-fPIC
" 깃발.라이브러리는 컴파일 시 링크 목록에 포함된다(즉:LDOPTS+=-lmylibS
이름을 가진 라이브러리 파일의 경우mylibS.a
. 이 두 가지 차이점은 공유 객체나 DLL이 공유 아카이브의 기능을 DLL 내에서만 사용하지 않고 다른 프로그램에서 사용할 수 있도록 정적 연결을 원할 경우 이 추가 플래그가 필요하다는 것이다.이것은 누군가가 당신에게 정적 라이브러리를 제공할 때 유용하며, 당신은 그것을 SO로 재포장하고자 할 때 유용하다.도서관은 컴파일 시간에 출석해야 한다.
추가 업데이트
"의 구별.DLL
" 그리고 "shared library
"그 당시 내가 근무했던 회사(Windows 개발자들이 리눅스 개발로 옮겨가도록 강요당하고, 용어까지 고착됨)에서 단지 (조용하고, 부정확한) 구어체일 뿐, 위에서 언급된 설명들을 고수하고 있었다.
또한 후행 "S
「도서관 명칭의 문자 그대로, 「기록 보관소」의 경우는, 그 회사에서 사용하는 관례일 뿐, 업계에서는 일반적으로 사용하지 않았다.
정적 라이브러리(.a)는 링커에 의해 생산된 최종 실행 파일에 직접 연결될 수 있는 라이브러리로서, 실행 파일이 배포될 시스템에 라이브러리를 포함할 필요가 없다.
공유 라이브러리(.so)는 연결되었지만 최종 실행 파일에 내장되지 않은 라이브러리여서 실행 파일이 실행될 때 로드되며 실행 파일이 배포된 시스템에 있어야 한다.
윈도우즈(.dll)의 동적 링크 라이브러리는 리눅스의 공유 라이브러리(.so)와 같지만 OS(윈도우즈 대 리눅스)와 관련된 두 구현 사이에는 다음과 같은 차이가 있다.
DLL은 내보내기 기능과 내부 기능의 두 가지 종류를 정의할 수 있다.내보낸 기능은 DLL 내에서뿐만 아니라 다른 모듈에서도 호출할 수 있도록 되어 있다.내부 기능은 일반적으로 정의된 DLL 내에서만 호출할 수 있다.
Linux의 SO 라이브러리는 모든 기호를 질문 프로세스에 사용할 수 있기 때문에 내보낼 수 있는 기호를 나타내는 특별한 내보내기 문장이 필요하지 않다.
나는 항상 DLL과 공유 개체는 같은 것에 대해 서로 다른 용어일 뿐이라고 생각해왔다. - Windows에서는 DLL이라고 부르고 UNIX 시스템에서는 동적으로 연결된 라이브러리라는 일반적인 용어로 공유 개체일 뿐이며 - UNIX에서는 .so를 여는 기능도 .so라고 부른다.dlopen()
'실제 도서관' 다음에).
그것들은 실제로 애플리케이션 시작 시에만 연결되지만 헤더 파일에 대한 당신의 검증 개념은 정확하지 않다.헤더 파일은 라이브러리를 사용하는 코드를 컴파일하기 위해 필요한 프로토타입을 정의하지만 링크 시간에 링커는 필요한 기능이 실제로 거기에 있는지 확인하기 위해 라이브러리 자체를 들여다본다.링커는 링크 시간에 어딘가에서 기능 본체를 찾아야 한다. 그렇지 않으면 오류가 발생할 것이다.또한 IT 부서는 프로그램이 컴파일된 이후 라이브러리 자체가 변경되었을 수 있기 때문에 런타임에 이 작업을 수행한다.플랫폼 라이브러리에서 ABI의 변화가 구 버전에 대해 편찬된 기존 프로그램을 깨는 것이기 때문에 ABI 안정성이 그만큼 중요한 이유다.
정적 라이브러리는 컴파일러에서 직접 만든 객체 파일들과 마찬가지로 컴파일러에서 바로 꺼낸 객체 파일들의 묶음일 뿐이므로 정확히 동일한 방식으로 링크커에 연결되고 사용되지 않은 비트는 정확히 동일한 방식으로 삭제된다.
나는 *NIX-land에 있는 내 친구들에게 그 미스터리를 명확히 하기 위해 Windows의 DLL에 대한 세부사항을 상세히 설명할 수 있다.
DLL은 공유 개체 파일과 같다.둘 다 각 OS의 프로그램 로더가 메모리에 로드할 준비가 된 이미지들이다.이 이미지들은 다양한 메타데이터 비트와 함께 제공되어 링커와 로더가 필요한 연결을 만들고 코드 라이브러리를 사용하는 것을 돕는다.
윈도 DLL에는 내보내기 테이블이 있다.내보내기는 이름 또는 테이블 위치(숫자)로 할 수 있다.후자의 방법은 "옛 학교"로 간주되어 훨씬 더 취약하다. DLL을 재건하고 테이블에서 기능의 위치를 변경하면 재앙으로 끝나는 반면, 진입점 연계가 이름만 대면 실질적인 문제는 없다.그러니, 문제 삼지 말고, 타사 공급업체 libs와 같은 "공룡" 코드와 함께 작업할 경우 해당 코드가 존재한다는 것을 알아두십시오.
윈도 DLL은 EXE(실행 가능한 애플리케이션)에 대해서처럼 컴파일하고 링크함으로써 구축되지만, DLL은 동적 로딩이나 링크타임 바인딩(SO에 대한 참조가 애플리케이션 바이너리의 메타데이터에 내장되어 있고 OS 프로그램 로드에 의해 응용 프로그램에 의해 사용되도록 되어 있는 것과 마찬가지로 독립적으로 서 있지 않도록 되어 있다.er는 참조된 SO를 자동으로 로드한다).SO가 다른 SO를 참조할 수 있듯이 DLL도 다른 DLL을 참조할 수 있다.
Windows에서 DLL은 특정 진입점만 사용할 수 있도록 한다.이것들은 "수출"이라고 불린다.개발자는 특수 컴파일러 키워드를 사용하여 기호를 외부에서 볼 수 있도록(다른 링커와 동적 로더로) 만들거나, 내보내기를 DLL 자체가 생성되는 링크 시간에 사용되는 모듈 정의 파일에 나열할 수 있다.기능 정의를 키워드로 장식해 기호 이름을 내보내는 것이 현대적 관행이다.또한 현재 컴파일 유닛 외부의 DLL에서 가져올 기호를 선언하는 키워드로 헤더 파일을 만들 수도 있다.자세한 내용은 __declspec(dllexport) 및 __declspec(dllimport) 키워드를 찾아보십시오.
DLL의 흥미로운 특징 중 하나는 표준 "부하/언로드" 핸들러 함수를 선언할 수 있다는 점이다.DLL을 로드하거나 언로드할 때마다 DLL은 경우에 따라 일부 초기화 또는 정리를 수행할 수 있다.이것은 DLL을 장치 드라이버나 공유 객체 인터페이스와 같은 객체 지향적 자원 관리자로 사용하는 것에 잘 매핑된다.
개발자가 이미 구축된 DLL을 사용하려면 "내보내기 라이브러리(*)"를 참조해야 한다.LIB) DLL 개발자가 DLL을 생성할 때 생성하거나, 런타임에 DLL을 명시적으로 로드하고 LoadLibrary() 및 GetProcAddress() 메커니즘을 통해 이름별로 진입점 주소를 요청해야 한다.대부분의 경우, LIB 파일(DLL의 내보낸 진입점에 대한 링커 메타데이터만 포함)에 대한 링크는 DLL이 사용되는 방식이다.동적 로딩은 일반적으로 프로그램 동작(추가 기능 또는 나중에 정의된 기능인 "플러그인"에 액세스)에서 "폴리모피즘" 또는 "런타임 구성성"을 구현하기 위해 예약된다.
Windows의 작업 방식은 때때로 혼란을 야기할 수 있다; 시스템은 를 사용한다.일반 정적 라이브러리(POSIX *.a 파일과 같은 아카이브)와 링크 시간에 응용 프로그램을 DLL에 바인딩하는 데 필요한 "내보내기 스텁" 라이브러리를 모두 참조하는 LIB 확장자.따라서 항상 *가 있는지 살펴봐야 한다.LIB 파일의 이름은 * 입니다.DLL 파일, 그렇지 않다면 *일 가능성이 크다.LIB 파일은 정적 라이브러리 보관 파일이며 DLL에 대한 바인딩 메타데이터를 내보내지 않는다.
고정 파일이 링크 시간에 응용 프로그램에 복사되고 공유 파일이 링크 시간에 확인되어 런타임에 로드된다는 점에서 당신이 옳다.
그dlopen
호출은 단순히 공유 객체에 대한 것이 아니라, 애플리케이션이 자신을 대신하여 런타임에 실행하기를 원하는 경우, 그렇지 않으면 공유 객체가 애플리케이션이 시작될 때 자동으로 로드된다.DLLS 및.so
같은 것이다.그dlopen
공정에 대한 더욱 세밀한 동적 적재 능력을 추가하기 위해 존재한다.당신은 사용할 필요가 없다.dlopen
응용 프로그램 시작 시에도 DLL을 열거나 사용할 수 있다.
나는 여기서 어떤 오해의 소지가 있다고 생각하지만, 적어도 소스 코드를 컴파일하는 데 사용되는 .h 버라이어티 중 헤더 파일은 링크 시간 동안 확실히 확인되지 않는다.
.h, 그리고 그 문제에 있어서 .c/.cpp 파일은 사전 처리를 포함하는 컴파일 단계 동안에만 관련된다.일단 객체 코드가 생성되면 헤더 파일은 링커가 일을 처리하기에 앞서 한참 전에 사라진다.
'Programing' 카테고리의 다른 글
로컬 저장소의 데이터를 사용하여 저장소를 초기화하는 방법? (0) | 2022.04.22 |
---|---|
페이지를 새로 고친 후 Vuex persistedState가 작동하지 않음 (0) | 2022.04.22 |
Vue CLI 쿠키 업데이트 또는 스토어 업데이트? (0) | 2022.04.22 |
mapGetters에서 단일 Vue getter 별칭 (0) | 2022.04.22 |
JLabel의 배경색 설정 방법 (0) | 2022.04.21 |