-
Linking대학/시스템소프트웨어 2022. 12. 11. 19:45
여러개의 분할된 ELF(Executable and Linkable Format)파일을 연결하는 과정을 linking이라고 부른다.
이 과정을 컴파일러의 linker가 수행하게 되는데, 그 동작 과정을 살펴보자.
- Static linking
1. Symbol resolusion
심볼이란 함수 이름, 변수 이름 등 사람이 보기 편한 이름들을 말하며 이는 symbol table에 의해 관리된다.
symbol resolusion은 이러한 심볼을 기계가 알아들을 수 있도록 이름을 주소값으로 바꾸는 작업을 말한다.
2. Relocation
분리되어있는 영역을 하나의 영역으로 합친다.
이 때, 코드의 위치가 변하게 되기 때문에 주소 값 역시 변하게 된다.
그 변화하는 주소 값을 계산하는 역할을 수행한다.
linking을 잘 활용하는 예시는
.o 파일들을 만들어놓고 필요한 것만 수정 후 link하는 식으로 관리하면 빌드 시간을 단축할 수 있다.
하지만, 링크할 파일이 수백개라면? 하나하나 입력하는게 무지 귀찮을 것이다.
따라서 필요한 실행파일을 하나로 묶어 관리하는 방법인 static library가 등장한다.
대표적으로 libc.a, libm.a 와 같은 라이브러리가 많이 쓰이는데, 이를 사용하는 방법은
컴파일시 -l<lib_name> 을 입력하는 것이다. (e.g. -lmine: mine 라이브러리 사용)
하지만 static library에도 치명적인 단점이 존재한다.
바로 동일한 코드를 프로세스마다 여러번 반복 사용한다는 점이다.
이러면 컴파일시에 저장공간이 낭비되고,
실행시 메모리 공간이 낭비되고,
무엇보다 문제 수정시 모든 파일을 다시 컴파일 해야하는 문제가 생긴다.
이런 문제를 해결하고자 나온 방법이 shared library이다.
- Dynamic linking
shared library, 다른 말로 dynamic link library, dll로 불리는 라이브러리는 동적 링크 방법을 이용해서
프로그램 컴파일시가 아닌, 프로그램 실행시 링크하는 방법이다.
심지어 실행 도중에도 링크할 수 있다.
동적 링크는 PLT(Procedure Linking Table)와 GOT(Global Offset Table)를 사용해 달성되는데
기존 정적 링크는 바로 라이브러리 코드로 링크되는데 반해
동적 링크는 PLT, GOT를 참조하여 라이브러리 코드로 링크된다.
다음과 같은 과정으로 진행된다.
1. printf를 호출한다. 따라서 PLT에 printf관련 GOT 포인터를 찾아간다.
2. GOT에 printf에 대한 포인터가 없다면?
3. 동적 링크 코드를 실행한다.
4. GOT에 printf에 대한 함수의 포인터를 링크한다.
1. printf를 호출한다. 따라서 PLT에 printf관련 GOT 포인터를 찾아간다.
2. GOT에 printf에 대한 함수의 포인터로 가서 printf함수를 호출한다.
위의 과정은 모두 프로그램이 시작할 때 동적으로 링크되는 과정을 살펴본 것이다.
이번에 살펴볼 내용은 프로그램 실행 중간에 동적으로 로딩하는 방법이다.
void (*addvec)(int *, int *, int *, int); void *handle = dlopen("./libvector.so", RTLD_LAZY); addvec = dlsym(handle, "addvec"); addvec(x, y, z, 2); dlclose(handle);
여기서 "addvec"은 "./libvector.so"에 있는 찾고자 하는 심볼의 이름이고,
addvec는 찾은 심볼의 메모리 주소를 리턴받는다.
'대학 > 시스템소프트웨어' 카테고리의 다른 글
Assembly (0) 2022.12.12 Memory Management (0) 2022.12.11 Synchronization (0) 2022.12.11 Threads (0) 2022.12.11 Inter-Process Communication (2) 2022.10.23