링킹은 여러개의 코드와 데이터를 모아서 연결하여 메모리에 로드될 수 있고 실행할 수 있는 한 개의 파일로 만드는 작업이다. 링킹은 컴파일 시에 수행할 수 있으며 이때 소스코드는 머신코드로 번역된다. 현대 시스템에서 링킹은 링커라고 부르는 프로그램에 의해서 자동으로 수행된다.
링커는 소프트웨어 개발시에 중요한 역할을 수행한다. 큰 규모의 응용프로그램을 한 개의 소스 파일로 구성하는 대신 별도로 수정할 수 있고, 컴파일할 수 있는 보다 관리할만한 규모의 더 작은 모듈들로 나눌 수 있다.
대부분의 컴파일 시스템은 사용자를 대신해서 언어 전처리기, 컴파일러, 어셈블러, 링커를 필요에 따라 호출하는 컴파일러 드라이버를 제공한다.
드라이버는 먼저 전처리기(ccp) 를 돌리고 이것은 c소스파일 main.c를 ASCII 중간파일인 main.i로 번역한다.
다음으로 드라이버는 C 컴파일러(ccl) 를 돌려서 main.i를 ASCII 어셈블리 언어파일인 main.s로 번역해준다.
그 다음에 드라이버는 어셈블러(as) 를 돌려서 main.s를 재배치 가능한 바이너리 목적파일 main.o로 번역한다.
마지막으로 링커(ld) 는 필요한 시스템 목적파일들과 함께 실행가능 목적파일을 생성하기 위해 main.o와 다른 파일(something.o)을 연결한다.
ELF 헤더는 이 파일을 생성한 워드 크기와 시스템의 바이트 순서를 나타내는 16바이트 배열로 시작한다. ELF 헤더의 나머지는 링커가 목적파일을 구문분석하고 해석하도록 하는 정보를 포함하고 있다.
쉘은 로더라고 알려진 메모리 상주 운영체제 코드를 호출해서 쉘의 내장 명령어에 대응되지 않는 단어가 올라왔을 때, 이 단어를 실행 가능 목적파일의 이름이라 가정하고 이 프로그램을 실행한다.
로더는 디스크로부터 실행 가능한 목적파일 내의 코드와 데이터를 메모리로 복사하고 이 프로그램의 첫 번째 인스트럭션, 즉 엔트리 포인트로 점프해서 프로그램을 실행한다. 이렇게 프로그램을 메모리로 복사하고 실행하는 과정을 로딩이라고 부른다.
x86-64 리눅스 시스템에서 코드 세그먼트 주소는 주소 0x40000에서 시작하고 뒤이어 데이터 세그먼트가 온다. 런타임 Heap은 데이터 세그먼트 다음에 따라온다 (malloc을 통해서 동적 메모리 할당이 이루어 지는 곳). 이 다음에는 공유 모듈들을 위해 예약된 영역이 존재하며, 사용자 스택은 가장 큰 합법적 사용자 주소(2^48 - 1) 아래에서 시작해서 더 작은 메모리 주소 방향인 아래로 성장한다.
이를 도식화 해서 나타낸 그림이 위와 같다.
더 간단히 표현한 그림도 찾아서 올려봄.