Linux 에서 동적 링크 라 이브 러 리 를 찾 을 수 없습니다.

9552 단어 운영 체제
현재 한 프로그램 에서 컴 파일 을 마 친 후에 자신 이 컴 파일 하여 생 성 한 동적 라 이브 러 리 파일 을 찾 을 수 없다 는 오류 가 발생 하여 매우 난처 하 다.과감하게 자 료 를 찾 아 해결 하고 비교적 완 선 된 글 을 복사 하 다.
주소:http://www.cnblogs.com/wiessharling/p/3431753.html
원문의 내용 은 다음 과 같다.
Linux 에서 동적 링크 라 이브 러 리 를 찾 을 수 없습니다.
 
1. 정적 라 이브 러 리 생 성 정적 라 이브 러 리 는 AR 도 구 를 사용 합 니 다. 사실은 AR 은 archive 라 는 뜻 입 니 다.
$ar cqs libhello.a hello.o

2. 동적 라 이브 러 리 생 성 은 gcc 로 이 루어 집 니 다. 여러 버 전이 존재 할 수 있 기 때문에 보통 버 전 번 호 를 지정 합 니 다.
$gcc -shared -o libhello.so.1.0 hello.o

3、 , :
  linux  ,       /usr/lib /lib , 
         libxxxx.a,   xxxx   lib   ;
         libxxxx.so.major.minor,xxxx   lib   ,major     ,minor      
 
4、                  (   )   :
              (    )   ,             ,           ,             (dynamic linker/loader) 
       elf         ,   ld-linux.so*     ,      elf     DT_RPATH  —    LD_LIBRARY_PATH—/etc/ld.so.cache     — /lib/,/usr/lib               
     : export LD_LIBRARY_PATH=’pwd’ 
 
5、  ldd  ,                           :
ldd                    , 
       # ldd /bin/lnlibc.so.6 
        => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2 
        => /lib/ld- linux.so.2 (0×40000000) 
         ln       libc    ld-linux   
 
6、  nm  ,                (T             ,U          ,        ,W        ,          )。:
                        ,nm                  ,                  。

nm 열 거 된 기 호 는 매우 많 습 니 다. 흔히 볼 수 있 는 것 은 세 가지 가 있 습 니 다.
  • 하 나 는 라 이브 러 리 에서 호출 되 었 으 나 라 이브 러 리 에서 정의 되 지 않 았 습 니 다 (다른 라 이브 러 리 지원 이 필요 함 을 표시 합 니 다). U 로 표시 합 니 다.
  • 하 나 는 라 이브 러 리 에서 정 의 된 함수 로 T 로 표시 하 는 것 이 가장 흔 하 다.
  • 다른 하 나 는 이른바 '약 한 상태' 기호 이다. 그들 은 라 이브 러 리 에서 정의 되 지만 다른 라 이브 러 리 의 동명 기호 에 의 해 덮어 쓸 수 있 고 W 로 표시 할 수 있다.

  • 예 를 들 어 개발 자가 위 에서 언급 한 hello 라 이브 러 리 에서 printf () 를 인 용 했 는 지 알 고 싶다 고 가정 합 니 다.
        $nm libhello.so | grep printf 

    printf 가 U 클래스 기호 인 것 을 발견 하면 printf 가 인용 되 었 음 을 설명 하지만 라 이브 러 리 에 정의 되 지 않 았 습 니 다.
    이 를 통 해 알 수 있 듯 이 hello 라 이브 러 리 를 정상적으로 사용 하려 면 다른 라 이브 러 리 지원 이 있어 야 합 니 다. ldd 도 구 를 사용 하여 hello 가 어떤 라 이브 러 리 에 의존 하 는 지 확인 하 십시오.
      $ldd hello libc.so.6=>/lib/libc.so.6(0x400la000) /lib/ld-linux.so.2=>/lib/ld-linux.so.2 (0x40000000)
    위의 결 과 를 통 해 printf 가 최종 적 으로 어디 에 정의 되 었 는 지 계속 볼 수 있 습 니 다. 관심 이 있 으 면 go on 할 수 있 습 니 다.
     
    7. AR 도 구 를 사용 하면 정적 라 이브 러 리 를 만 들 수 있 고 정적 라 이브 러 리 에. o 파일 이 포함 되 어 있 는 것 을 볼 수 있 습 니 다. 즉, 원본 파일 로 구성 되 어 있 습 니 다.
    AR - t libname. a 를 사용 하여 정적 라 이브 러 리 가 o 파일 로 구성 되 어 있 는 지 볼 수 있 습 니 다.
    ar q libname. a xxx1. o xxx2. o xxx3. o.. xxxn. o 를 사용 하여 정적 라 이브 러 리 를 생 성 할 수 있 습 니 다.
     
    Linux        ,      :
     
     、gcc/g++         :
    -shared: ( T , W ), 。
    -fPIC: ( ) , , , , , 。
    -L: ,-L.
    -ltest: test, , lib, .so
    LD_LIBRARY_PATH: 。
    root , /etc/ld.so.conf , /sbin/ldconfig ,
             root  ,        LD_LIBRARY_PATH        。 
            ,          :
        1、  ,                  “-I” include   ,        “-L”    ,    “-l”   ,   ldd     ,             so  ,             LD_LIBRARY_PATH  /etc/ld.so.conf           。                   。
     
     、             : 
    1. ld gcc/g++ -L;
    2. gcc LIBRARY_PATH, ;
          export LIBRARY_PATH=$LIBRARY_PATH:data/home/billchen/lib 
    3. /lib /usr/lib /usr/local/lib, compile gcc 。
     
     、     、         : 
    1. ;
        2.     LD_LIBRARY_PATH         ,                ;
          export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:data/home/billchen/lib 
    3. /etc/ld.so.conf ;
    4. /lib;
    5. /usr/lib。
     
     、                :
                       ,  libmysqlclient.a libmysqlclient.so     :
         Linux ,            ,gcc/g++     ,        。

    다음 방법 을 사용 하여 커 넥 터 에 파 라 메 터 를 전달 하여 동적 라 이브 러 리 를 연결 하 는 지, 정적 라 이브 러 리 를 연결 하 는 지 확인 할 수 있 습 니 다.
     
    - WI, - bstatic - libname / / gcc / g + + 정적 라 이브 러 리 연결 지정
    사용:
      gcc/g++ test.c -o test -WI,-Bstatic -llibname
     
    - WI, - Bdynamic - libname / / gcc / g + + 동적 라 이브 러 리 연결 지정
    사용:
      gcc/g++ test.c -o test -WI,-Bdynamic -llibname
     
    완전히 정적 으로 추가 하려 면 - static 파 라 메 터 를 사용 하여 모든 라 이브 러 리 를 정적 으로 실행 가능 한 프로그램 에 연결 합 니 다. 이렇게 생 성 된 실행 가능 한 프로그램 은 그 어떠한 라 이브 러 리 에 도 의존 하지 않 습 니 다. 동료 들 이 발생 하 는 문 제 는 이렇게 컴 파일 된 프로그램 이 매우 크 고 공간 을 차지 하 는 것 입 니 다.
     
     、      : 
    LIBRARY_PATH :
    LD_LIBRARY_PATH :
     
     、       :

    cp newlib.so oldlib.so, core ;
    :
    rm oldlib.so cp newlib.so oldlib.so

    mv oldlib.so oldlib.so_bak cp newlib.so oldlib.so

    왜 cp newlib. so oldlib. so 를 사용 할 수 없 습 니까?
    so 파일 을 교체 할 때 프로그램 이 멈 추 지 않 는 상태 에서 cp new. so old. so 방식 으로 프로그램 이 사용 하 는 동적 라 이브 러 리 파일 을 교체 하면 실행 중인 프로그램 이 무 너 집 니 다.
     
    해결 방법:
    해결 방법 은 'rm + cp' 나 '뮤 직 비디오 + cp' 를 사용 하여 직접 'cp' 의 조작 방법 을 대체 하 는 것 이다.
    Liux 시스템 의 동적 라 이브 러 리 는 두 가지 사용 방법 이 있 습 니 다. 실행 시 동적 링크 라 이브 러 리, 동적 로드 라 이브 러 리 와 프로그램 제어 하에 사용 합 니 다.
     
    1. 왜 프로그램 이 멈 추 지 않 는 상황 에서 프로그램 이 사용 하 는 so 파일 을 cp 명령 으로 직접 교체 하면 프로그램 이 무 너 집 니까?많은 학생 들 이 업무 중 에 이러한 문 제 를 겪 었 습 니 다. so 파일 을 교체 할 때 프로그램 이 멈 추 지 않 는 상황 에서 cp new. so old. so 방식 으로 프로그램 이 사용 하 는 동적 라 이브 러 리 파일 을 교체 하면 실행 중인 프로그램 이 무 너 지고 종 료 됩 니 다.
    이것 은 cp 명령 의 실현 과 관련 이 있 습 니 다. cp 는 대상 파일 의 inode 를 바 꾸 지 않 습 니 다. cp 의 대상 파일 은 원본 파일 이 아 닌 겹 쳐 진 파일 의 속성 을 계승 합 니 다.실제로 이 는 이렇게 이 루어 졌 다. strace cp libnew. so libold. so 2 > & 1 | grep open. * lib. * soopen ("libnew. so", O RDONLY | O LARGEFILE) = 3open ("libold. so", O WRONLY | O TRUNC | O LARGEFILE) = 4 cp 에서 "O WRONLY | O TRUNC" 를 사용 하여 대상 파일 을 열 었 을 때 원 so 파일 의 미 러 가 의외로 파괴 되 었 다.이러한 동적 링크 기 ld. so 는 so 파일 의 함수 입구 에 접근 할 수 없습니다.이 로 인해 Segmentation fault, 프로그램 이 무 너 집 니 다.ld. so 로 so 파일 을 불 러 오고 '위치 추적' 메커니즘 이 복잡 합 니 다.
     
    2. 어떻게 프로그램 을 멈 추 지 않 고 so 파일 을 교체 하고 프로그램 이 무 너 지지 않도록 보증 합 니까?정 답 은 'rm + cp' 나 '뮤 직 비디오 + cp' 를 사용 하여 직접 'cp' 의 조작 방법 을 대체 하 는 것 이다.
    새로운 so 파일 libnew. so 로 오래된 so 파일 libold. so 를 교체 할 때 다음 과 같은 방법 을 사용 하면 rm libold. so / 커 널 이 libold. so 를 사용 하고 있다 면 inode 노드 는 즉시 삭제 하지 않 습 니 다.cp libnew. so libold. so 는 이러한 방법 을 사용 합 니 다. 대상 파일 libold. so 의 inode 는 이미 바 뀌 었 습 니 다. 원래 의 libold. so 파일 은 "ls" 로 볼 수 없 지만, inode 는 커 널 이 인용 할 때 까지 진정 으로 삭제 되 지 않 았 습 니 다.
    (즉, rm libold. so, 이때 ld. so 가 libold. so 에 추가 되 어 있 으 면 커 널 은 libold. so 의 inode 노드 를 참조 하고 있 습 니 다. rm libold. so 의 inode 가 진정 으로 삭제 되 지 않 았 습 니 다. ld. so 가 libold. so 에 대한 인용 이 끝나 야 inode 가 진정 으로 삭 제 됩 니 다. 그러면 프로그램 은 무 너 지지 않 습 니 다. 오래된 libold. so 를 사용 하고 있 기 때문에 다음 에 libold. so 를 사용 할 때 이미 교체 되 었 습 니 다.새 libold. so 사용)
    마찬가지 로 뮤 직 비디오 는 파일 이름 만 바 꾸 었 을 뿐 inode 는 변 하지 않 고 새 파일 은 새로운 inode 를 사용 했다.이러한 동적 링크 기 ld. so 는 여전히 원래 파일 의 inode 를 사용 하여 오래된 so 파일 에 접근 합 니 다.그래서 프로그램 은 여전히 정상적으로 운행 할 수 있다.
    (즉: mv libold. so * * * 후 프로그램 이 동적 라 이브 러 리 를 사용 하거나 오래된 inode 노드 를 사용 하면 다음 에 libold. so 를 사용 할 때 새로운 libold. so 를 사용 합 니 다)
    여기까지 "cp new exec file old exec file" 이라는 명령 을 직접 사용 할 때 시스템 은 이러한 조작 을 금지 하고 "cp: cannot create regular file ` old ': Text file busy" 라 는 힌트 를 줍 니 다.이때, 우리 가 사용 하 는 방법 은 여전히 "rm + cp" 또는 "mv + cp" 로 직접 "cp" 를 대체 하 는 것 입 니 다. 이것 은 위 에서 언급 한 so 파일 의 교체 와 같은 이치 가 있 습 니 다.
    그런데 왜 시스템 은 cp 가 실행 가능 한 프로그램 을 덮어 쓰 는 것 을 막 고 so 파일 을 덮어 쓰 는 것 을 막 지 않 습 니까?
    이것 은 Linux 에 Demand Paging 메커니즘 이 있 기 때 문 입 니 다. 이른바 'Demand Paging' 입 니 다. 쉽게 말 하면 시스템 이 물리 적 메모리 비용 을 절약 하기 위해 프로그램 이 실 행 될 때 모든 페이지 (page) 를 메모리 에 불 러 오지 않 고 시스템 에 접근 할 필요 가 있 을 때 만 불 러 옵 니 다.'Demand Paging' 은 실행 중인 프로그램 미 러 (파일 자체 가 아 닌 것 을 주의 하 십시오) 가 예상 치 못 하 게 수정 되 지 않도록 요구 하기 때문에 커 널 은 프로그램 을 시작 한 후 이 프로그램 미 러 의 inode 를 잠 글 것 입 니 다.
    so 파일 에 대해 서 는 ld. so 로 불 러 옵 니 다. ld. so 는 사용자 상태 프로그램 이기 때문에 inode 를 잠 글 권리 가 없고 커 널 의 파일 시스템 바 텀 과 결합 해 서 는 안 됩 니 다.
     

    좋은 웹페이지 즐겨찾기