jeongjinyeong's homepage

2026-09-02

CSAPP ch1.

컴퓨터 시스템 : 하드웨어 + 시스템 소프트웨어

컴파일

: 어떤 언어로 쓰인 프로그램을 다른 언어의 동등한 프로그램으로 번역하는 것

#include <stdio.h>

int main() {
    printf("hello, world!\n");
    return 0;
}

1. 전처리 : .c 소스 텍스트 → 전처리된 소스 텍스트(.i)

gcc -E hello.c -o hello.i

전처리

main 함수 위로 헤더 파일의 내용이 들어온 것을 확인할 수 있다.

2. 컴파일 : 전처리된 C 코드(.i) → 어셈블리 텍스트(.s)

gcc -S hello.i -o hello.s

컴파일

어셈블리 텍스트로 변경된 것을 확인할 수 있다.

3. 어셈블 : 어셈블리 텍스트(.s) → 오브젝트 파일(.o)

gcc -c hello.s -o hello.o

어셈블

어셈블리가 기계어 바이트로 바뀐 것을 확인할 수 있다.

4. 링크 : 오브젝트 파일들(.o) + 라이브러리 → 실행 파일

gcc hello.o -o hello

모든 컴파일 과정이 이러한 것은 아니다. 어셈블리로 작성한 코드는 고급 언어를 어셈블리로 변환하는 컴파일까지의 단계는 필요하지 않을 것이고, 기계어로 직접 실행 파일을 작성하는 것도 가능하다. 또한 고급 언어라 하더라도 Go, Rust, Java 등에는 독립된 전처리 단계가 없고, Java의 JIT 컴파일과 같이 컴파일 과정이 다른 경우도 있다.

명령어 집합 구조(Instruction Set Architecture)

컴퓨터의 하드웨어와 소프트웨어 간의 인터페이스를 정의하는 개념

기계어를 작성하기 위해 필요한 모든 정보를 말하며, 단순히 명령어(instruction)의 집합뿐만 아니라 레지스터, 메모리 모델, 주소 지정 방식(addressing mode) 등을 포함한 모든 정보를 의미한다.

하나의 표준이 존재하는 게 아니라 각 회사가 목표로 하는 설계 철학, 성능 요구 사항, 전력 소비, 응용 분야 등에 따라 다양하게 존재한다.

프로세스와 스레드

우선 메모리 구조에 대해 이미지로 간략히 확인하고 가겠다.

메모리 구조

메모리 구조

프로세스

: 작업의 단위로 실행 중인 프로그램

각 프로세스는 자신만의 가상 주소 공간(페이지 테이블), [코드, 전역 변수, 힙, 스택] 영역, 열린 파일 디스크립터 테이블, 시그널 핸들러, 현재 작업 디렉터리 등을 갖는다.

스레드

: 실행 흐름의 단위로, 같은 프로세스의 스레드들은 자원을 공유

각 스레드는 각자 실행을 하기 위해 레지스터 상태, 스택 영역, 스케줄링 상태, errno, TLS 등을 갖는다.

동시성과 병렬성

동시성

병렬성

동시성과 병렬성

추상화

복잡한 시스템에서 본질적인 부분만 남기고 세부 사항을 감추는 것

필자가 학습할 때는 세탁기 비유로 학습했는데, 이미지는 찾지 못했지만 적절한 비유라고 생각이 돼서 설명해보겠다.

세탁기를 사용할 때 세탁물을 넣고 버튼만 누르면 세탁이 되고, 작업이 끝나면 세탁물을 돌려받는다. 이때 내부에서 사람이 들어가서 빨래를 하는지, 어떤 식으로 작동하는지는 우리가 알 필요가 없다.

이러한 개념을 사용하는 API, 함수, 네트워크 계층 구조 등 모두 추상화라고 할 수 있고, 앞서 설명한 명령어 집합 구조에서 해당 명세만 따르면 하드웨어와 소프트웨어가 서로에 대해 이해하지 않아도 되는 것 역시 추상화라고 볼 수 있다.


부족한 내용이나 잘못된 정보가 있다면 jeong.jinyeong95@gmail.com으로 연락 바랍니다.