1. Linker(링커)
링커는 프로그래머가 작성한 여러 소스 파일을 하나로 연결해주는 역할을 한다.
이러한 링커의 역할에 의해 응용 프로그램을 하나의 큰 파일이 아니라, 작은 단위의 소스파일로 나누어서 효율적으로 프로그래밍을 할 수 있다. 우리가 평소에 코딩할 때 자주 사용하는 라이브러리들도 링커 덕분에 사용할 수 있는 것이다.
링커가 분리된 소스파일을 연결해주는 역할을 하기 때문!
이렇게 모듈 단위(개별 소스 파일)로 코딩을 하면 시간적으로도 공간적으로도 효율성이 높다.
프로그래머가 전체 코드를 수정하고 컴파일하는 대신 , 수정이 필요한 소스 파일의 내용만 컴파일 하면 되기 때문에 코드 관리의 효율성이 훨씬 높다.
2. Linking - 링커가 하는 일
1) Symbol resolution
define과 reference라는 symbol을 정의한다.
define은 공간을 확보하는 것을 의미하고 reference는 확보된 공간(define)을 사용하는 것을 의미한다.
예시와 함께 이해하는 게 더 쉽다..
swap 함수를 정의하는 것 = define symbol swap
swap 함수를 사용하는 것 = reference symbol swap
*xp(포인터 변수)를 정의 하는 것 = define symbol xp
&x(변수 x의 주소값)를 할당하는 것 = reference symbol x
이렇게 정의된 symbol들은 각각이 주소값을 갖는 symbol table(array)에 저장된다.
2) Relocation
분리된 코드들을 하나로 묶어주는 역할.
오브젝트 파일에 있는 상대적인 위치(relative locations)들을 실행가능한 파일의 절대적인 메모리 위치(final absolute memory locations)로 재배치 한다.
* 정확한 메모리 번지 수는 아직 모름 loading할 때 주소가 정해지니까... 그때 알게 된다.
그리고 나서 모든 references들은 새로운 위치를 반영하여, symbols을 업데이트한다.
3. 실제로 해보자.
이 두 파일(main, swap)을 링킹하기 위해서 아래와 같이 컴파일 해주면 된다.
$gcc -01 -marm -fno-section-anchors -g -c -o main.o main.c
$gcc -01 -marm -fno-section-anchors -g -c -o swap.o swap.c
$gcc -01 -fno-section-anchors -g -o p main.o swap.o
@---------------------------------------------------------------@
@ -c : just compile
@ -fno-section-anchoers :
@ -g : 디버깅 gdb 사용
첫번째와 두번째 코드는 relocate object로의 컴파일 코드이고, 세번째 코드가 링킹을 위한 코드이다.
-marm : arm 코드로 변환하는 역할을 한다. 디폴트 값은 thumb이다.
이렇게 명령을 하고 나면 소스 파일은 relocatable object file으로 변환되고, linker를 통해 'p'라는 파일로 링킹된다.
아래 그림을 통해 직관적인 이해를 할 수 있다.
main 함수에서 swap 함수를 사용할 때 main 함수는 swqp함수의 주소를 어떻게 알 수 있을까?
=> **오브젝트 파일은 항상 symbol 인덱스를 갖는다.
swap함수는 main함수에서 정의된 buf 배열의 주소를 어떻게 알 수 있을까?
링커가 오브젝트와 주소들을 연결해준다!(relocates)
이 사진 파일에서 Relocate와 Executable의 의미를 정확히 이해해두는 것이 좋겠다.
민트색으로 표기된 .bss는 아직 초기화가 안된 데이터가 저장되는 공간이다. data 부분에서 확인해보면 00000000으로 저장된다. 사실 어떤 값이 들어가도 상관없지만..!
4. 링커가 정의하는 심볼 세 가지
'm' module이 있다고 치고 세가지 심볼을 예시를 통해 이해해보자.
1) Global Symbols: 정의는 m에서 했지만 다른 모듈에서 사용하는 것. 따라서 연결(symbol resolution)이 필요하다. non-static한 symbol
2) External Symbols: Global symbols와 반대. 다른 모듈에서 정의된 것을 m에서 사용하는 것.
3) Local Symbols: m내에서 정의되고 m 내에서 사용. static한 symbol. 여기서 말하는 local은 지역 변수와는 의미가 다르다. 지역변수는 링커가 관리를 하지 않기 때문이다. local symbols는 링커가 모듈 m 안에서 관리.
*지역변수와 전역변수*
갑자기?라고 생각할 수 있지만 연관있음
살짝 유용한 tmi를 말하자면,, 지역변수는 linker가 관여를 하지 않는다. 당연한 게, 지역변수는 함수가 호출될 때에만 생성이 되고 해당 함수가 종료되면 즉시 파괴되므로 자신이 속해있는 함수가 실행 중 일 때만 메모리를 차지하기 때문이다. 그래서 지역변수와 전역변수의 사용이 메모리 할당과 프로그램 실행시간에 많은 영향을 끼치는 것이다!
'CS > OS' 카테고리의 다른 글
[OS] 프로세스 | 프로세스의 상태 | PCB | context switching (0) | 2023.04.07 |
---|---|
[OS] 컴퓨터 시스템 구조 | 저장장치 계층 | 프로그램 실행 과정 | 커널 | 동기식/비동기식 IO | DMA (0) | 2023.04.06 |
[OS] Mode bit | Device Controller | Interrupt (0) | 2023.03.17 |
[OS] os를 공부하기 위해 알아야 하는 용어들 (0) | 2023.03.10 |
[OS] 운영체제 (4) | 2023.03.09 |