교육과정에서 배우고 리눅스 스터디에서 복습한 내용입니다.

소스코드 등이 있어서 리눅스 스터디라고 하지 않고 따로 제목을 만들어 분리하였습니다.

앞으로도 소스코드를 사용한 개별적 주제들을 제목을 따로 만들어 분리, 게시글 작성하겠습니다.

 

 

 

 

1. 라이브러리(labrary)란

 - 무엇인가 유용한 지식을 한 곳에 모아둔 것

 - 프로그램에서 라이브러리는 컴파일 과정을 거쳐서 만든 오브젝트파일(.o)을 한 곳에서 관리하는 것을 의미한다

    (즉 반복적으로 사용되는 함수들을 매번 컴파일 할 필요없이 하나의 함수로 떼내어 어디서든 사용가능하게 함)

 - 관례상 파일명 끝이 .a나 .so로 끝난다. 동일한 이름의 so와 .a가 잇을 경우 .so가 우선된다.(a는 archive라는 의미)

 - 라이브러리는 오브젝트 파일(.o)들과 이 오브젝트 파일에 대한 목록을 가진목차(index)로 구성된다

 - 리눅스에서는 ar이라는 gnu유틸리티를 이용하여 라이브러리 아카이브를 관리한다

 - 리눅스의 기본적인 라이브러리 검색 경로는 /lib, /usr/lib/, /usr/local/lib등 이 있다

 - ar옵션 참조

    http://forum.falinux.com/zbxe/index.php?document_srl=549870&mid=lecture_tip

 

※ 참고 - http://blog.naver.com/free2824/60055895383

 - SDK(Software Development Kit): 소프트웨어를 개발하는 도구(개발 프로그램(도구)+API+관련문서로 구성됨, 흔히 SDK를 API라고 이야기하지만 정확히는 다르다)

 - API(Application Programming Interface): 응용프로그램을 만들기 위한 인터페이스(인터페이스: 개발 도구를 이용해서 프로그래밍할수 있게 제공하는 라이브러리들을 의미한다. 즉, API는 응용프로그램을 만들기 위한 개발도구의 라이브러리들을 의미한다)

 

 

2. 정적 라이브러리

 - 파일생성시 라이브러리를 포함하여 사용한다

 - 라이브러리 연동과정이 필요없음

 - 다른 프로그램과 공유하지 않기 때문에 각각의 프로그램마다 라이브러리를 메모리에 맵핑하기 때문에 메모리 활용성이 떨어진다

 

 

3. 동적(공유) 라이브러리

 - 라이브러리를 하나의 메로리 공간에 맵핑후 여러 프로그램에서 공유하여 사용

 - 메모리 용량 절약, 라이브러리 업테이트등의 유연성이 있다.

 - 라이브러리 의존성에 따른 관리가 필요하다

 

=> 동적 라이브러리는 .bin과 .so가 있어야하지만, 정적 라이브러리는 .bin만 있어도 실행이된다.

 

※ 동적라이브러리와 공유라이브러리의 차이

 - 공유 라이브러리:
    실행될 때 올라감. 한 번 올라가면 다시 로드할 필요 없음.
    수동으로 라이브러리 올리는 경우.


 - man dlopen: 동적 링크 로더에 대한 프로그래밍 인터페이스
     이렇게 해서 올리게 되면 동적 라이브러리라고 부름.
     실행할 때 올라가게 되면 그냥 공유 라이브러리라고 함.

 

 

4. 라이브러리 과정 없이 컴파일 하기

 - 현재 경로(./)에 myfunc.h hello.c lib디렉터리가 있고, lib내에는 myfunc.c가 있다

 - 한번에 하기

    gcc -o hello hello.c lib/myfunc.c

 - 나누어하기

    gcc -c hello.c

    gcc -c lib/myfunc.c

    gcc -o hello myfunc.o hello.o

 - 실행하기

    ./hello

 

 

5. 정적라이브러리 사용하기

 - ./lib/에서

    gcc -c myfunc.c

    ar r libmylib.a myfunc.o => mylib.a생성하는 명령(r[ab][f][u]  - replace existing or insert new file(s) into the archive)

    ar t libmylib.a => mylib.a가 가지고 있는 오브젝트 파일 목록보기( t - display contents of archive)

 - ./로 경로변경

    gcc -o hello hello.c -lmylib => 이렇게 하면 현재 경로에 mylib.a가 없기 따문에 오류가 출력된다(-l옵션: 라이브러리 추가)

    (-l 옵션을 사용할 때는 대상 라이브러리 파일의 이름에서 앞의 lib와 뒤의 .a를 때고 -l옵션을 넣으면된다)

    gcc -o hello hello.c -lmylib -L./lib => hello.c와 mylib.a를 참초하여 hello를 생성(-L옵션: 라이브러리 위치를 지정하는 옵션)

    ./hello => 실행

   

 

6. 동적(공유)라이브러리 사용하기

 - 파일명 규칙: lib파일명.so.버전번호(ex: libio.so.1.01)

 

 - ./lib/에서

    gcc -fPIC -c myfunc.c => 위치 독립적인 코드 생성하여, 로드되는 메모리 주소가 달라도 돌아가게 한다(아래 설명 참조)

    gcc -shared -W1,-soname,libio.so.1 -o libio.so.1.01 myfunc.o

    => -shared 옵션 : 가능한 한 공유 라이브러리와 링크하고 공유 라이브러리가 없는 경우에는 정적 라이브러리와 링크

    => -W1 옵션: ,뒤에 오는 옵션들이 gcc를 거치지 않고 바로 링커에게 전달되도록 해준다. 즉, 링커가 사용할 옵션을 입력하기 위한 옵션

    => -soname,libio.so.1: 라이브러리에서 해당so에 대한 name을 지정한다. 다른 응용프로그램들은 이 이름을 참조하여 라이브러리를 찾게 된다.

    => -o libio.so.1.01 myfunc.o: myfunc.o를 이용하여 libio.so.1.01라는 결과물(공유라이브러리)을 생성한다

   

 - 최종 실행파일을 만들기 전에 심볼릭 링크 2개를 만들어야한다

    ./lib/에서

    ln -s libio.so.1.01 libio.so.1 => libio.so.1.01의 바로가기 'libio.so.1'를 생성한다(로더가 이링크를 가지고 실행한다)

    ln -s libio.so.1 libio.so => libio.so.1의 바로가기 'libio.so'를 생성한다(gcc컴파일러는 .so로만 파일을 찾기 때문에 생성)

    => 주의할점은 심볼릭 링크의 대상이 libio.so.1.01이 아닌 위의 생성한 심볼릭 링크 이름인 libio.so.1으로 해야한다

    =>(이러한 이유는 강사님도 잘 모르신다고 했다) 하지만, 참고한 사이트에서는 생성물인 libio.so.1.01를 입력하였다.

    =>개인적인 생각으로는 ln -s libio.so.1.01 libio.so로 해도 상관없다. gcc는 libio.so를 링킹하고, 그 결과물을 실행하면 로더는 libio.so의 대상인 libio.so.1.01을 라이브러리 경로에서 찾을 것이다.

    =>참조 사이트와 강사님의 차이에 대해 고찰한 결과는 아래 7. 을 참조한다.

 - 이제 실행파일을 만들기 위해 컴파일한다

    ./에서

    gcc -o hello hello.c -lio -L./lib

    =>-lio는 libio.so의 lib를 빼고 -l을붙인것이다.(정적라이브러리에서 ar 명령으로 생성한 libmylib.a와 똑같이 lib가 생략된다)

   

 - 실행하면 libio.so의 경로를 찾을수 없다고 오류가 생긴다(따라서 경로를 등록해준다)

    vim /etc/ld.so.conf

    내부에 /root/work/lab/elp/lab03_mylib/lib(라이브러리가 위치한 해당경로, 절대경로로 해야 한다)입력

    ldconfig =>로더설정을 재부팅

    ./hello =>실행됨

 

 

7. 참조 사이트와 강사님의 차이에 대해 고찰한 결과

 - 강사님이 하신방법

    gcc컴파일러가 공유라이브러리를 인식하기 위해 libio.so를 생성

    실행파일 실행시 로더는 libio.so를 공유라이브러리로서 인식하고 libio.so에 링크된 대상이 libio.so.1이기때문에 로더는 이를 참조

    (라이브러리 경로를 추가하였기 때문에) 로더가 라이브러기를 해당 경로로 들어가 대상을 찾음.

    libio.so.1는 libio.so.1.01로 연결되어 있기때문에 최종적으로 로더는 libio.so.1.01를 공유라이브러리로서 참고하게됨

 

 - 사이트에서 하는 방법(http://damul21c.tistory.com/49)

    gcc컴파일러가 공유라이브러리를 인식하기 위해 libio.so를 생성(단 libio.so.1.01와 연결)

    실행파일 실행시 로더는 libio.so를 공유라이브러리로서 인식하고, libio.so는 심볼릭 링크이니 연결된 libio.so.1.01를 찾고자한다.

    (기본 라이브러리 경로에 libio.so.1.01를 이동시켜놨기 때문에) 로더가 라이브러리를 기본경로로 들어가 대상을 찾음

 

 - 강사님이 하신 방법의 장점

    라이브러리를 업데이트 하게 되면 이름이 바뀐다(libio.so.1.01 -> libio.so.1.02). 이경우 링크만 새로 연결하면 문제가 없다

    예를들어 

    ① gcc -shared -W1,-soname,libio.so.1 -o libio.so.1.02 myfunc.o로 새로운 라이브러리를 생성하고 ln -s libio.so.1.02 libio.so.1해서 링크만 새로 생성하면

    ② 실행파일 hello에는 libio.so가 들어가 있고, libio.so.1으로 연결되어 있으니, 로더는 여전히 libio.so.1를 참조할 것이고, 결과적으로 libio.so.1.02가 실행되게 된다.

    ③ 만일 사이트의 방식대로하면 실행파일을 생성하기 위한 심볼릭 링크인 libio.so와 실행파일을 새로운 libio.so.1.02에 맞추어 다시 생성해야한다(즉, 링크뿐만아니라 실행파일 또한 새로 생성해야한다)

 


8. gcc의 -fPIC옵션
 - 각각의 .c파일을 PIC(Position Independent Code)가 되도록 컴파일 한다는 의미이다.
 - 옵션은 -fpic와 -fPIC 두가지가 있는데,
    -fpic는 좀더 고속으로 코드를 생성할수 있지만, cpu에 따라 -fpic로 생성할수 있는 GOT(Glocal Offset Table)의 크기에 제한이 있고,
    -fPIC는 cpu와 상관없이 .c파일을 PIC로 만든다.(보통 -fPIC옵션을 사용하는 것 같다.)

    =>x86에서는 -fpic와 -fPIC가 동일하다

 

 - -fPIC옵션을 사용하는 이유
    공유를 위한 위치독립적 코드를 생성하기 위해서이다.
    위 옵션을 사용하지 않으면 실행시 코드를 메모리에 재배치하게된다.
    즉 실행은 되지만 실제로 공유되는 것이 아니다.
    한마디로 요약하면 재배치 과정을 제거하기 위해서 사용한다.

 

 - 비 PIC 버전과 PIC 버전의 차이
    -fPIC옵션을 사용하여 실행파일을 생성하면 .text코드가 비 PIC에 비해 증가한다(.text섹션 용량증가)
    하지만 재배치에 필요한 정보(.rel.dyn)가 없기 때문에 전체적인 용량은 감소한다
    => readelf명령의 -S옵션으로 이를 확인할 수 있다.

    또한, 
    비 PIC 버전은 재배치 과정이 있기 때문에 매 호출마다 시간이 소요되며,
    재배치가 필요한 부분의 코드를 재작성 하기 위해 copy on write가 발생한다. 이에따라 다른 프로세스와 텍스트를 공유할 수 없게 된다
    하지만 PIC 버전은 재배치 과정이 필요없기 때문에 처음 호출에만 시간이 걸리고 그 이후 호출시간은 없으며,
    재배치를 하지 않기 때문에 .text섹션을 다른 프로세스들과 공유할 수 있다(공유라이브러리를 사용하는 이유이기도 하다)


 - 참조
    http://devanix.tistory.com/198

    http://damul21c.tistory.com/49
    http://erato1004.tistory.com/entry/정적-공유-라이브러리
 - 재배치의 개념(로더의 기능중 하나이다)
    http://hbesthee.tistory.com/1410
 - elf형식의 섹션구성(상세)
    http://rootfriend.tistory.com/entry/%EB%A7%81%ED%81%ACLinkers-%EC%99%80-%EB%A1%9C%EB%8D%94Loaders

 

   

   

   

 

'Study > Linux' 카테고리의 다른 글

리눅스 스터디 - 7  (0) 2018.02.05
리눅스 스터디 - 6  (0) 2018.02.04
리눅스 스터디 - 5  (0) 2018.01.21
리눅스 스터디 - 4  (0) 2018.01.21
리눅스 스터디 - 3  (0) 2018.01.15

+ Recent posts