2. 컴파일러, 링커, 로더들의 동작: 기본 사항

a.c와 b.c 두 개의 프로그램이 있다고 가정하고, 쉘 프롬프트에서 a.c와 b.c를 gcc를 이용하여 아래와 같은 명령을 수행하면 다음과 같은 일들이 순서대로 수행된다.

gcc a.c b.c

cpp, cc1, as는 GNU의 전처리기, 컴파일러, 어셈블러를 각각 나타내며, GCC 배포본 안에 들어있다.

위와 같은 스텝은 b.c에도 똑같이 적용되어 b.o라는 오브젝트 파일을 하나 더 생성하게 된다. 그러면 링커의 작업은 이러한 두 개의 오브젝트 파일들(a.o, b.o)을 입력으로 받아서 최종적으로 실행가능한 파일을 만드는 것이다.

ld [other-command-line options] /tmp/a.o /tmp/b.o -o a.out

최종적으로 만들어진 실행파일(a.out)은 이제 로드될 준비가 되었다. 이것을 실행시키기 위해서 우리는 쉘 프롬프트상에서 아래와 같이 타이핑한다.

./a.out

그러면 쉘은 로더를 불러 a.out의 코드와 데이터를 메모리로 복사하고, 프로그램내의 제일 처음으로 제어권을 넘긴다. 여기서 말하는 로더는 execve라는 것으로 실행가능한 오브젝트 파일의 코드와 데이터를 메모리로 로드하고 그 프로그램의 첫번째 명령어가 저장된 주소로 점프함으로써 프로그램을 수행하게 한다.

a.out이라는 명칭은 a.out 오브젝트 파일들안에 있는 어셈블러의 출력물에서 그 유래를 찾을 수 있다. 그 이후로 오브젝트 형식은 다양하게 바뀌어 왔지만, 그 이름은 계속 사용되어지고 있다.