컴파일 과정을 간단하게 살펴보자면,
전처리 Pre-processing | 주석 제거, 매크로 인라인화 등의 작업 수행 |
↓↓↓ | |
컴파일 Compile | 컴파일러가 C 소스코드를 컴파일하여 어셈블리어 코드로 변환 |
↓↓↓ | |
어셈블리 Assembly | 어셈블러가 어셈블리어 코드를 기계어 코드로 변환 |
↓↓↓ | |
링크 Linking | 링커가 기계어 코드와 공유 라이브러리를 합쳐서 최종 실행파일 생성 |
좀 더 확장해서 보면,
1. 코드 에디터(Editor)를 이용해서 C File 을 작성한다.
2. 컴파일러(Compiler)가 C File 을 ASM File 로 컴파일한다. 이 때 오류가 발생하면 에러 메시지를 띄운다.
3. 어셈블러(Assembler)가 ASM File 을 Object File(기계어 파일)로 변환한다.
4. 링커(Linker)가 .o 파일과 라이브러리들을 합쳐서 실행가능한 기계어 파일(Executable Object File)을 생성한다.
5. 로더(Loader)가 Disk 의 내용을 Memory 로 올린다.
이 과정을 직접 리눅스 환경에서 shell 명령어 해석기를 이용하여 실습해보기
// 에디터로 c file 생성
vi hello.c
// 컴파일러로 ASM file 생성
// 이 때, -S 옵션은 컴파일러만 수행하게 하도록 한다. 이 옵션을 안붙이면 실행파일 생성까지 바로 끝난다.
gcc -S hello.c
// 어셈블러로 .o file(object file; 바이너리 파일) 생성
as -o hello.o hello.s
// 링커로 실행파일 만들기
/usr/lib/gcc/i486-linux-gnu/3.4.6/collect2 /usr/lib/i486-linux-gnu/crt1.o /usr/lib/i386-linux-gnu/crti.o /usr/lib/i386-linux-gnu/crtn.o /usr/lib/gcc/i486-linux-gnu/3.4.6/crtbegin.o /usr/lib/gcc/i486-linux-gnu/3.4.6/crtend.o hello.o -lc -dynamic-linker /lib/ld-linux.so.2
// 로딩한 후 최종적으로 실행하기
./a.out
이 때, 컴퓨터 시스템에서 로더 Loader 가 필요한 이유를 좀 더 살펴보자.
CPU는 바이트(bite) 단위 접근이 가능한데, Disk의 경우 섹터(sector) 단위 접근만을 지원한다. 따라서 바이트(bite) 단위 접근을 지원하는 DRAM으로 로더가 로딩을 해주는 작업이 필요하다. 결국 Disk 는 sector 단위, DRAM과 CPU는 bite 단위라는 접근 인터페이스의 차이 때문이다.
'컴퓨터 공학 > 시스템 프로그래밍' 카테고리의 다른 글
[리눅스 프로그래밍] 파일 디스크립터 File Discriptor (0) | 2021.10.10 |
---|---|
[리눅스 프로그래밍] 시스템 콜 system call (0) | 2021.10.10 |
[리눅스 프로그래밍] 리눅스의 다중 사용자 시스템, 권한 설정 (0) | 2021.10.10 |
[리눅스 프로그래밍] 리눅스의 세 가지 중요 개념 : 파일시스템, 프로세스, 스트림 (0) | 2021.10.09 |
[리눅스 프로그래밍] 리눅스 추상화의 층구조 (0) | 2021.10.09 |