SO 파일을 로드할 때 끝에 버전이 추가되는 이유는 무엇입니까?

SO 파일을 로드할 때 끝에 버전이 추가되는 이유는 무엇입니까?

저는 CMake와 Ninja를 사용하여 C++로 작성된 테스트 실행 파일을 빌드하고 있습니다. GCC 4.8을 사용하고 있습니다. 우분투 14를 사용하고 있습니다.

CMake를 실행하여 ninja 빌드 스크립트를 구성한 다음 ninja를 실행하여 빌드합니다. CMake 스크립트에서 libcrypto.so대상 종속성으로 다른 openssl 파일을 지정합니다.*.so

실행 파일을 실행할 때 다음 오류가 발생합니다.

공유 라이브러리 로드 오류: libcrypto.so.1.0.0: 공유 개체 파일을 열 수 없습니다. 해당 파일 또는 디렉터리가 없습니다.

libcrypto.so파일은 테스트 실행 파일 옆에 있습니다.

-rw-r--r-- 1 robert domain users 1796847 Apr 20 15:43 libboost_wave.so
-rw-r--r-- 1 robert domain users  410916 Apr 20 15:43 libboost_wserialization.so
-rw-r--r-- 1 robert domain users 2251519 Apr 21 11:28 libcrypto.so
-rw-r--r-- 1 robert domain users  701627 Apr 20 15:43 libEGL.so
-rw-r--r-- 1 robert domain users 4255871 Apr 20 15:43 libGLES_CM.so
-rw-r--r-- 1 robert domain users 7550551 Apr 20 15:43 libGLESv2.so
-rw-r--r-- 1 robert domain users  949113 Apr 17 14:34 libsqlite.so
-rw-r--r-- 1 robert domain users  496298 Apr 21 11:28 libssl.so
-rwxr-xr-x 1 robert domain users 3099250 Apr 21 11:30 Test_UI_String*

(내가 실행 중인 실행 파일은 입니다 Test_UI_String.)

CMake는 실행 파일 옆에 공유 라이브러리를 출력하도록 설정되어 있습니다. 왜냐하면 Windows(저에게 개발에 가장 익숙한)와 같은 다른 플랫폼에서는 DLL 파일을 찾아서 로드하려면 EXE 옆에 있어야 하기 때문입니다.

1.0.0왜 라이브러리 파일 끝에 추가되는지 혼란 스럽습니다 . 종속성을 연결했을 때 libcrypto.so위에 표시된 디렉터리에 있는 것과 동일한 이름을 가졌기 때문에 끝에 버전 번호 없이 이를 찾아야 합니다 .

여기서의 동작을 더 잘 이해하고 싶지만 주요 질문은 기본적으로 예상대로 작동하도록 하는 방법(실행 파일과 동일한 디렉터리에 있는 라이브러리 종속성 찾기)에 관한 것입니다.

답변1

링커는 실행 파일(또는 다른 공유 라이브러리)을 빌드할 때 이름의 -l접두사 와 접미사로 lib사용되도록 요청된 라이브러리를 검색합니다 . .so예를 들어 요청 -lcrypto하면 libcrypto.so.

라이브러리를 찾으면 링커는 해당 라이브러리에서 soname이라는 메타데이터 조각을 읽습니다. 그런 다음 soname은 빌드 중인 실행 파일에 로그인되며 런타임 시 동일한 라이브러리를 다시 검색할 때 사용되는 이름입니다. 물론, soname은 링크 시 실제로 찾은 라이브러리의 이름과 다를 수 있습니다.

이 기능의 사용 사례는 시스템에 호환되지 않는 여러 라이브러리 버전을 동시에 설치하는 기능입니다. 일반적으로 사용되는 방법은 다음과 같습니다.

먼저, 이 규칙이 없으면 어떤 일이 일어날지 설명하겠습니다.

개발 헤더( .h파일)는 특정 버전의 라이브러리와 연결되며 .so파일에는 해당 버전도 포함됩니다.

/usr/include/mylibrary.h
/usr/lib/libmylibrary.so

애플리케이션은 myapp이 버전의 라이브러리에 대해 컴파일되고 /usr/lib/libmylibrary.so런타임에 로드됩니다.

나중에 라이브러리가 새 버전으로 업그레이드되었습니다. .h파일이 .so새 버전으로 대체됩니다. 안타깝게도 새 버전에는 호환되지 않는 ABI가 있습니다.

이제 myapp실행 시 충돌이 발생하거나 정의되지 않은 동작이 나타납니다. 왜냐하면 하나의 ABI를 사용하여 한 버전에 대해 컴파일했지만 런타임 시 다른 버전을 로드하기 때문입니다.

무슨 일이야그리고소네임 규칙:

라이브러리는 다음과 같이 설치됩니다.

/usr/include/mylibrary.h
/usr/lib/libmylibrary.so -> libmylibrary.so.1
/usr/lib/libmylibrary.so.1

그리고 /usr/lib/libmylibrary.so.1거기에 soname을 삽입했습니다 libmylibrary.so.1.

myapp빌드할 때 을 찾으 /usr/lib/libmylibrary.so나 링커는 심볼릭 링크를 따라가서 실제로 로드합니다 /usr/lib/libmylibrary.so.1. 또한 실제로 soname이 libmylibrary.so.1기록됩니다 myapp. 런타임 시 심볼릭 링크를 우회하여 직접 myapp로드됩니다 ./usr/lib/libmylibrary.so.1

나중에 라이브러리는 호환되지 않는 ABI가 포함된 새 버전으로 업그레이드되었습니다. .h파일이 .so새 버전으로 대체됩니다. libmylibrary.so.2새 파일이 나타납니다. 이전 버전의 콘텐츠는 libmylibrary.so.1변경되지 않습니다.

/usr/include/mylibrary.h
/usr/lib/libmylibrary.so -> libmylibrary.so.2
/usr/lib/libmylibrary.so.1
/usr/lib/libmylibrary.so.2

이제 실행되면 myapp계속 로드 libmylibrary.so.1되고 예상대로 실행됩니다. 그러나 다른 새 응용 프로그램이 설치되거나 myapp응용 프로그램 자체가 다시 컴파일되면 기호 링크를 따르고 새 버전이 사용됩니다.


현재 보고 있는 문제는 애플리케이션을 링크할 때 링커가 soname 을 포함하는 라이브러리를 찾았다는 것입니다 libcrypto.so.1.0.0.

사본이 libcrypto.sosoname if를 사용하여 생성 되었습니까 libcrypto.so.1.0.0?

또 다른 가능성(여기서 가장 가능성이 높음)은 libcrypto.so복사본에 soname이 없지만 링커가 실제로 찾아서 사용하는 것입니다.체계(OpenSSL에서) libcrypto.so, 이름이 유래된 곳입니다.

관련 정보