유 닉 스/Linux 환경 에서 정적/동적 라 이브 러 리 를 만 들 고 사용 합 니 다.

10139 단어 C++clinuxunixC#
창고 의 역할
대체적으로 라 이브 러 리 의 존 재 는 두 가지 이유 가 있 는데 하 나 는 코드 의 재 활용 이 고 다른 하 나 는 성명 과 실현 의 분리 이다.기능 이 비슷 한 사용 모듈 을 라 이브 러 리 로 밀봉 하여 코드 의 재 활용,관리 와 배 포 를 매우 간단 하 게 만 들 었 습 니 다.예 를 들 어 유명한 오픈 소스 그래 픽 라 이브 러 리 ncurses 는 스스로 컴 파일 할 수 있 고 이미 컴 파일 된 라 이브 러 리 파일 을 직접 사용 할 수 있 습 니 다.또한 라 이브 러 리 는 바 이 너 리 파일 이기 때문에 특정한 의미 에서 기능 의 실현 부분 을 숨 기 면 상업 코드 의 보호 에 방식 을 제공 합 니 다.라 이브 러 리 파일 은 링크 방식 과 시기 에 따라 동적 라 이브 러 리 와 정적 라 이브 러 리 로 나 눌 수 있 습 니 다.다음은 리 눅 스 환경 에서 의 생 성과 사용 방법 을 소개 합 니 다.
정적 연결 라 이브 러 리
정적 라 이브 러 리 는 프로그램의 링크 단계 에서 사용 되 는 코드 가 실행 가능 한 파일 의 라 이브 러 리 로 직접 연 결 됩 니 다.정적 링크 의 실행 가능 한 프로그램 은 필요 한 모든 라 이브 러 리 함 수 를 포함 합 니 다.모든 라 이브 러 리 함 수 는 프로그램 에 연 결 됩 니 다.이러한 프로그램 은 완전한 것 으로 외부 라 이브 러 리 의 지원 이 필요 하지 않 습 니 다.정적 링크 프로그램의 장점 중 하 나 는 설치 하기 전에 환경 준 비 를 하지 않 아 도 된다 는 것 이다.Linux 에서 정적 라 이브 러 리 의 확장 자 는 보통.a 입 니 다.대상 파일(o)의 압축 파일(archive)이나 포장 일 뿐 입 니 다.또한 링크 를 할 때 그 중의 기호(함수,변수 이름 등)를 신속하게 찾 을 수 있 도록 정적 라 이브 러 리 에는 그 중의 기호 에 대한 색인 도 포함 되 어 있 습 니 다.정적 라 이브 러 리 를 만 드 는 과정 은 매우 간단 합 니 다.컴 파일 에 필요 한 도 구 를 제외 하고 사용 할 명령 은 두 개의 AR 과 ranlib 만 있 습 니 다.AR 은 각 대상 파일 을 압축 파일 할 수 있 습 니 다.ranlib 는 AR 에서 생 성 된 압축 파일(즉 정적 라 이브 러 리 파일)을 색인 할 수 있 습 니 다.현재 몇 개의 원본 파일 이 있다 고 가정 합 니 다:plus.c,sub.c 및 해당 하 는 헤더 파일,그리고 라 이브 러 리 파일 의 함 수 를 호출 하 는 메 인 파일 main.c 가 있 습 니 다.그들의 내용 은 각각 plus.c 입 니 다.
#include "plus.h"
int
plus(int a, int b)
{
    return a + b;
} 

 sub.c,
#include "sub.h"
int
sub(int a, int b)
{
    return a - b;
} 

 main.c,
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "plus.h"
int
main(int argc, char **argv)
{
    int a = plus(1, 2);
    printf("%d
", a); return 0; }

 다음은 plus.c 와 sub.c 를 컴 파일 하여 정적 라 이브 러 리 libmath.a 로 만 들 고 순서대로 실행 합 니 다.
$ cc main.c -L. -lmath -o main
$ ./main
동적 연결 라 이브 러 리
동적 라 이브 러 리 는 정적 라 이브 러 리 와 비슷 하고 각 대상 파일 의 집합 이기 도 합 니 다.그러나 정적 링크 프로그램 에 비해 동적 링크 는 실행 가능 한 프로그램 이 훨씬 작 습 니 다.이러한 프로그램 이 실 행 될 때 외부 공유 함수 라 이브 러 리 의 지원 이 필요 하기 때문에 완전 하지 않 은 것 같 습 니 다.프로그램 체 가 작은 것 을 제외 하고 동적 링크 는 패키지 가 필요 한 라 이브 러 리 를 지정 할 수 있 으 며 라 이브 러 리 를 패키지 에 불 러 올 필요 가 없습니다.동적 링크 기술 은 여러 실행 중인 프로그램 이 하나의 라 이브 러 리 를 공유 하도록 허용 합 니 다.그러면 같은 코드 의 여러 복사 가 메모리 에서 차지 하 는 상황 이 발생 하지 않 습 니 다.이러한 원인 으로 인해 현재 대부분의 프로그램 은 동적 링크 기술 을 사용한다.리 눅 스에 서 의 확장 자 는 보통.so 입 니 다.그러나 링크 를 연결 할 때 실행 가능 한 파일 에 연결 되 지 않 고 실행 할 때(필요 할 때)운영 체제 의 동적 로드 모듈 에서 메모리 로 동적 으로 불 러 오고 실행 가능 한 파일 주소 공간의 해당 위치 로 연결 합 니 다.동적 링크 라 이브 러 리 의 생 성 도 컴 파일 과 압축 파일 두 단계 로 나 뉘 지만 이 두 단계 에서 서로 다른 명령 옵션 을 사용 해 야 합 니 다.우선,원본 파일 을 위치 와 무관 한 코드(PIC:Position Independent Code)가 되 는 대상 파일 로 컴 파일 해 야 합 니 다.이 코드 는 메모리 의 어느 위치 에 도 추가 할 수 있 지만,추가 장치 가 필요 하지 않 습 니 다.이러한 형식 에 대해 서 는 와 에서 비교적 상세 한 설명 을 참고 할 수 있다.다음은 이 위치 와 상 관 없 이'압축 파일'을'so 파일'로 해 야 합 니 다.전체 과정 은 하나의 도구 만 있 으 면 됩 니 다.즉,gcc 입 니 다.위의 원본 파일 인지 다음 명령 을 수행 합 니 다.
$ cc -c -fpic plus.c sub.c
$ cc -shared -o libmath.so *.o

이렇게 해서 plus.o 와 sub.o 를 포함 하 는 동적 라 이브 러 리 파일 libmath.so 가 만 들 어 졌 습 니 다.그 중에서 cc(gcc 의 심 볼 릭 링크)명령 의-fpic 또는-fpic 옵션 은 위치 와 무관 한 대상 파일 을 만 들 고-shared 옵션 을 사용 하면 최종 동적 라 이브 러 리 파일 을 만 들 수 있 습 니 다.동적 라 이브 러 리 파일 을 사용 하 는 방법 은 두 가지 가 있 습 니 다.하 나 는 운영 체제 의 동적 로드 모듈(예 를 들 어 ld-linux.so.2)을 실행 할 때 동적 라 이브 러 리 를 불 러 오 는 것 입 니 다.다른 하 나 는 코드 에서 dl 라 이브 러 리 동적 로드 라 이브 러 리 파일 을 사용 하 는 것 입 니 다.먼저 다음 방법 을 소개 하 겠 습 니 다.이 방법 을 사용 하려 면 실행 가능 한 파일 을 컴 파일 할 때 라 이브 러 리 이름과 경 로 를 알려 야 합 니 다.(자신 이 작성 한 동적 라 이브 러 리 에 대해 서 는)

$ cc main.c -L. -lmath -o main

이 때 실행 가능 한 파일 main 이 생 성 되 었 습 니 다.위의 명령 은 libmath.so 에 해당 하 는 대상 코드 를 main 에 연결 하지 않 았 습 니 다.(main 과 정적 링크 의 main 크기 를 비교 해 볼 수 있 습 니 다)라 이브 러 리 에서 main.c 에 사용 되 는 기 호 를 찾 고 확인 할 수 있 습 니 다.그러나 이 main 은 현재 정상적으로 실행 되 지 않 습 니 다.이것 은 시스템 이 동적 라 이브 러 리 를 찾 는 경로 문제 와 관련 되 어 있 습 니 다.시스템 은 보통 지정 한 디 렉 터 리(표준 경로)에서 필요 한 라 이브 러 리 파일 만 찾 습 니 다.표준 경로 에서 필요 한 라 이브 러 리 를 찾 을 수 없 으 면 환경 변 화 량 LD 로 갑 니 다.LIBRARY_PATH(존재 한다 면)가 지정 한 디 렉 터 리 에서 찾 습 니 다.찾 을 수 없 으 면 오류 가 발생 합 니 다.libmath.so 는 main 의 현재 디 렉 터 리 에 있 기 때문에 현재 디 렉 터 리 는 표준 경로 의 열 에 있 지 않 습 니 다.libmath.so 를 찾 고 불 러 올 수 있 도록 표준 경로 에 넣 을 수 있 지만 더 좋 은 방법 은 해당 디 렉 터 리 를 LD 에 추가 하 는 것 입 니 다.LIBRARY_PATH 변수 중.다음 명령 실행:

$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. #       
$ export LD_LIBRARY_PATH #        ,    shell   
$ ./main
3

다음은 dl 라 이브 러 리 를 사용 하여 동적 라 이브 러 리 를 불 러 옵 니 다.dl 라 이브 러 리 의 함수 가 매우 간결 하지 않 습 니 다.main.c 코드 를 보십시오.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include "plus.h"
int
main(int argc, char **argv)
{
    void * lib_handle = dlopen("./libmath.so", RTLD_LAZY);
    if(lib_handle)
    {
        int (*plus_ptr)(int, int) = dlsym(lib_handle, "plus");
        if(plus_ptr)
        {
            int a = plus_ptr(1, 2);
            printf("%d
", a); } dlclose(lib_handle); } return 0; }

 main.c 에서 먼저 dlopen 을 사용 하여 필요 한 동적 라 이브 러 리 를 엽 니 다.그 중에서 매개 변 수 는 RTLD 입 니 다.레이 지 는 이 라 이브 러 리 를 호출 해 야 할 때 만 불 러 옵 니 다.dlopen 은 핸들 을 되 돌려 줍 니 다.dlsym 은 이 핸들 과 기 호 를 사용 하여 해당 함수 의 주 소 를 얻 습 니 다.여 기 는 int(*)(int,int)함수 포인터 로 plus 함수 의 주 소 를 받 습 니 다.다음 에 얻 은 함수 포인터 로 해당 함 수 를 호출 하고 마지막 으로 dlclose 함 수 를 통 해 핸들 을 닫 습 니 다.이 프로그램 을 컴 파일 하려 면 dl 동적 링크 라 이브 러 리 를 사용 해 야 하기 때문에 gcc-ldl 옵션 을 사용 해 야 합 니 다.
$ cc main.c -ldl -o main
$ ./main
so 와 a 파일 의 대비
마지막 으로 libmath.a 와 libmath.so 파일 의 내용 을 첨부 하고 objdump 의-d 옵션 을 사용 하여 보 았 습 니 다:libmath.a,
In archive libmath.a:

plus.o:     file format elf32-i386
Disassembly of section .text:
00000000 <plus>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	8b 45 0c             	mov    0xc(%ebp),%eax
   6:	8b 55 08             	mov    0x8(%ebp),%edx
   9:	8d 04 02             	lea    (%edx,%eax,1),%eax
   c:	5d                   	pop    %ebp
   d:	c3                   	ret    

sub.o:     file format elf32-i386
Disassembly of section .text:
00000000 <sub>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	8b 45 0c             	mov    0xc(%ebp),%eax
   6:	8b 55 08             	mov    0x8(%ebp),%edx
   9:	89 d1                	mov    %edx,%ecx
   b:	29 c1                	sub    %eax,%ecx
   d:	89 c8                	mov    %ecx,%eax
   f:	5d                   	pop    %ebp
  10:	c3                   	ret

libmath.so:
libmath.so:     file format elf32-i386
Disassembly of section .init:
00000324 <_init>:
 324:	55                   	push   %ebp
 325:	89 e5                	mov    %esp,%ebp
 327:	53                   	push   %ebx
 328:	83 ec 04             	sub    $0x4,%esp
......
0000044c <plus>:
 44c:	55                   	push   %ebp
 44d:	89 e5                	mov    %esp,%ebp
 44f:	8b 45 0c             	mov    0xc(%ebp),%eax
 452:	8b 55 08             	mov    0x8(%ebp),%edx
 455:	8d 04 02             	lea    (%edx,%eax,1),%eax
 458:	5d                   	pop    %ebp
 459:	c3                   	ret
 45a:	90                   	nop
 45b:	90                   	nop

0000045c <sub>:
 45c:	55                   	push   %ebp
 45d:	89 e5                	mov    %esp,%ebp
 45f:	8b 45 0c             	mov    0xc(%ebp),%eax
 462:	8b 55 08             	mov    0x8(%ebp),%edx
 465:	89 d1                	mov    %edx,%ecx
 467:	29 c1                	sub    %eax,%ecx
 469:	89 c8                	mov    %ecx,%eax
 46b:	5d                   	pop    %ebp
 46c:	c3                   	ret
 46d:	90                   	nop
 46e:	90                   	nop
 46f:	90                   	nop
......

Disassembly of section .fini:

000004a8 <_fini>:
 4a8:	55                   	push   %ebp
 4a9:	89 e5                	mov    %esp,%ebp
 4ab:	53                   	push   %ebx
 4ac:	83 ec 04             	sub    $0x4,%esp
 4af:	e8 00 00 00 00       	call   4b4 <_fini+0xc>
 4b4:	5b                   	pop    %ebx
 4b5:	81 c3 40 1b 00 00    	add    $0x1b40,%ebx
 4bb:	e8 d0 fe ff ff       	call   390 <__do_global_dtors_aux>
 4c0:	59                   	pop    %ecx
 4c1:	5b                   	pop    %ebx
 4c2:	c9                   	leave
 4c3:	c3                   	ret

이 를 통 해 알 수 있 듯 이 상대 적 으로 a,so 에는 많은 추가 코드 세그먼트 가 있 는데 그 중에서 비교적 중요 한 것 은세그먼트 와세그먼트.그들 은 각각 전기 와 후기 처리 작업 을 진행한다.예 를 들 어보통 dlopen 이 돌아 오기 전에.so 라 이브 러 리 의 초기 화 작업 을 수행 합 니 다(C++에 서 는 전역 구조 나 정적 대상 의 구조 함수 일 수 있 습 니 다).
다음으로 이동:http://www.dutor.net/index.php/2010/07/dynamic-static-library/

좋은 웹페이지 즐겨찾기