SO (공유 객체) 번호는 어떻게 작동합니까?


123

Linux에서 공유 객체는 "so 숫자"를 사용한다는 것을 알고 있습니다. 즉, 다른 버전의 공유 객체에는 다른 확장자가 제공됩니다.

  • example.so.1
  • example.so.2

아이디어는 두 가지 버전의 라이브러리가 시스템에 존재할 수 있다는 것입니다 (Windows의 "DLL 지옥"과 반대). 이것이 실제로 어떻게 작동하는지 알고 싶습니다. 종종 나는 그것이 최신 버전이 어디에 있는지에 example.so대한 상징적 링크라는 것을 안다 . 그러면 이전 버전의 응용 프로그램에 따라 응용 프로그램이 어떻게 올바르게 식별됩니까? 어떤 숫자를 사용해야하는지에 대한 규칙이 있습니까? 아니면 이것은 단순히 관습입니까? 소프트웨어 바이너리가 시스템간에 전송되는 Windows와 달리 시스템에 최신 버전의 공유 객체가있는 경우 소스에서 컴파일 할 때 이전 버전에 자동으로 연결되는 경우입니까?example.so.2.2example.so

나는 이것이 관련이 있다고 생각 ldconfig하지만 어떻게되는지 모르겠습니다.

답변:


87

바이너리 자체는 자신이 의존하는 공유 라이브러리의 버전을 알고 구체적으로 요청합니다. ldd종속성을 표시하는 데 사용할 수 있습니다 . 광산 ls은 :

$ ldd /bin/ls
    linux-gate.so.1 =>  (0xb784e000)
    librt.so.1 => /lib/librt.so.1 (0xb782c000)
    libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
    libc.so.6 => /lib/libc.so.6 (0xb76dc000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
    /lib/ld-linux.so.2 (0xb784f000)
    libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)

당신이 볼 수 있듯이, 그것은 예 가리키는 libpthread.so.0뿐만 아니라, libpthread.so.


심볼릭 링크의 이유는 링커 때문입니다. libpthread.so직접 연결 gcc하려면 플래그 -lpthread를 지정하면 lib접두사와 .so접미사가 자동으로 추가 됩니다. .so.0접미사 를 추가하도록 지시 할 수 없으므로 기호 링크는 최신 버전의 lib를 가리키고 있습니다.


등호 "= ls"가 없어야합니다. "ldd ls"를 사용하십시오
bmacnaughton

1
@bmacnaughton ldd실행 파일의 전체 경로가 필요 하기 때문에 아마도 오류가 발생 합니다. =lszsh에서는이 작업을 수행하지만 모든 사용자가 해당 쉘을 사용하는 것은 아니기 때문에 변경했습니다
Michael Mrozek

흥미 롭군 우분투에서 bash를 실행 중이며 전체 경로없이 작동하는 것 같습니다. 설명 주셔서 감사합니다-나는 zsh를 사용하지 않습니다.
bmacnaughton

60

공유 라이브러리의 숫자는 Linux에서 라이브러리의 API를 식별하기 위해 사용되는 규칙입니다. 일반적으로 형식은 다음과 같습니다.

libFOO.so.MAJOR.MINOR

그리고 일반적으로 알 수 있듯이 libFOO.so에서 libFOO.so.MAJOR.MINOR 로의 심볼릭 링크가 있습니다. ldconfig는이 링크를 최신 버전으로 업데이트합니다.

MAJOR는 일반적으로 API가 변경 될 때 증가합니다 (새 진입 점이 제거되거나 매개 변수 또는 유형이 변경됨). MINOR는 일반적으로 버그 수정 릴리스 또는 기존 API를 중단하지 않고 새 API를 도입 할 때 증가합니다.

보다 광범위한 토론은 여기에서 찾을 수 있습니다 : 공유 라이브러리 해부


안녕 미구엘, 그것에 대해 감사합니다, 부끄러움 나는 위의 내용을 훌륭하게 보완하기 때문에 두 가지 대답을 받아 들일 수 없습니다. 나에게서 +1, 훌륭한 링크도 다시 한 번 감사드립니다!

4
그것은 거의 정확하지만 실제로 libFOO.so.MAJOR.MINOR(끝에 있지는 않습니다)
JonnyJD

6
이 대답은 너무 잘못되었습니다 . 첫째, 당신이 보는 숫자는 API와 관련이 없으며 순수한 ABI입니다. 둘째, 여기의 규칙은 당신이 제안하는 것처럼 시맨틱 버전 화가 아닙니다. 오히려 ld.so가 비교할 수있는 단일 라이브러리 버전 번호로 매핑하는 훌륭한 속성을 가진 libtool 규칙입니다 ( 자세한 내용 은 gnu.org/software/libtool/manual/html_node/… 참조 )
NewbiZ

23

공유 라이브러리는 다음 구성표에 따라 버전이 지정되어야합니다.

blah.so.X.Y.Z

어디

  • X = 이전 버전과 호환되지 않는 ABI 릴리스
  • Y = 이전 버전과 호환되는 ABI 릴리스
  • Z = 내부 변경 만-ABI에 변경 없음

hello.so.1다른 모든 숫자는 이전 버전과 호환되므로 첫 번째 숫자 만 라이브러리의 "버전"을 식별하는 데 필요한 유일한 숫자이므로 첫 번째 숫자 만 표시 됩니다.

ldconfig시스템에서 사용 가능한 공유 라이브러리 및 해당 라이브러리의 경로가 존재하는 위치에 대한 테이블을 유지 보수합니다. 다음을 실행하여이를 확인할 수 있습니다.

ldconfig -p

패키지가 Red Hat과 같은 것을 위해 빌드 될 때, 바이너리에서 호출되는 공유 라이브러리는 RPM 빌드 타임에 패키지의 종속성으로 조회 및 추가됩니다. 따라서 패키지를 설치할 때 hello.so.1설치 관리자는를 선택하여 시스템에 설치되어 있는지 여부를 찾습니다 ldconfig.

다음과 같은 작업을 수행하여 패키지의 종속성을 볼 수 있습니다.

rpm -qpR hello.rpm

이 시스템 (Windows와 달리)은 여러 버전의 hello.so시스템을 시스템에 설치하고 동시에 다른 응용 프로그램에서 사용할 수 있습니다.


이것이 가장 좋은 대답이라고 생각합니다.
Kemin Zhou

1
공유 라이브러리는 다음 구성표 (…)에 따라 버전이 지정되어야합니다. –이 문장에 대한 참조를 제공해 주시겠습니까?
Piotr Dobrogost

19

libNAME.so는 -lNAME으로 지정된 라이브러리를 처음 찾을 때 컴파일러 / 링커에서 사용하는 파일 이름입니다. 공유 라이브러리 파일에는 SONAME이라는 필드가 있습니다. 이 필드는 라이브러리 자체가 빌드 프로세스에 의해 공유 오브젝트 (so)에 처음 링크 될 때 설정됩니다. 이 SONAME은 실제로 공유 객체가 링크되어있는 링커가 실행 파일에 저장하는 것입니다. 일반적으로 SONAME은 libNAME.so.MAJOR 형식이며 라이브러리가 연결된 기존 실행 파일과 호환되지 않을 때마다 변경되며 필요에 따라 라이브러리의 두 주요 버전을 모두 설치 상태로 유지할 수 있습니다 (개발을 위해 하나만 지적 됨) 또한 마이너 버전의 라이브러리 간을 쉽게 업그레이드 할 수 있도록 libNAME.so.MAJOR는 일반적으로 libNAME.so.MAJOR.MINOR와 같은 파일에 대한 링크입니다. 새 부 버전을 설치하고 완료하면 이전 부 버전에 대한 링크가 업그레이드 된 라이브러리를 사용하기 위해 모든 새 실행을 즉시 업그레이드하는 새 부 버전을 가리 키도록 충돌합니다. 또한 내 답변보기Linux, GNU GCC, ld, 버전 스크립트 및 ELF 이진 형식-작동 방식

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.