컴퓨터 구조에 대한 이론 공부 요약

2026. 1. 27. 14:25이론 공부/컴퓨터 구조

내가 보려고 만든 컴퓨터 구조에 대한 요약

 

1. CPU 구성요소와 역할

CPU는 레지스터 / ALU / 제어장치로 구성된다.

  • 레지스터(Register): CPU 내부의 매우 빠른 저장공간으로, 주소만 저장하는 게 아니라 당장 실행/연산에 필요한 값들을 저장한다.
    예)
    • PC(Program Counter): 다음 실행할 명령어의 주소
    • IR(Instruction Register): 현재 가져온 명령어 자체
    • 범용 레지스터: 연산 데이터/중간 결과
    • SP(Stack Pointer), FLAGS/PSW
  • ALU(Arithmetic Logic Unit): 산술/논리 연산을 수행한다. (실제 계산 담당)
  • 제어장치(Control Unit): IR의 명령어를 **해석(디코드)**하고, 레지스터/ALU/메모리/버스에 제어 신호를 생성해 실행 흐름을 만든다.
    즉 “CPU 내부에서 무엇을 언제 어떻게 동작시킬지”를 조정한다.

 

2. 캐시-메모리-디스크 계층이 나뉘는 이유

계층이 나뉘는 이유는 속도/비용/용량의 트레이드오프를 해결하기 위함이며, 이를 지역성(Locality)(시간/공간 지역성)으로 “현실적으로 이길 수 있기 때문”이다.

  • CPU에 가까울수록 빠르지만 비싸고 용량이 작다.
  • 캐시는 보통 SRAM 기반이라 빠르지만 비싸고 용량이 작다. (캐시 라인 단위로 가져와 hit/miss가 성능을 좌우)
  • **메모리(RAM)**는 보통 DRAM 기반으로 캐시보다 느리지만 싸고 용량이 크다. 또한 휘발성이라 전원이 꺼지면 데이터가 사라지고, DRAM은 리프레시가 필요하다.
  • **디스크(SSD/HDD)**는 비휘발성이라 전원이 꺼져도 데이터가 유지되고 용량이 크며 상대적으로 저렴하지만 RAM보다 느리다.
    그래서 프로그램/데이터의 영구 저장은 디스크가 담당하고, 실행 중인 코드는 RAM/캐시로 올라와 사용된다.

 

3. 명령어 실행 흐름과 파이프라인이 왜 필요한가

컴퓨터는 디스크의 프로그램을 RAM으로 올리고, CPU는 이를 캐시에 올려 실행한다. CPU는 Fetch → Decode → Execute(→ Memory → Writeback) 같은 흐름으로 명령어를 처리한다.

  • 파이프라인이 필요한 이유는 “클럭에 맞추기 위해서”가 아니라, 명령어 처리 단계를 겹쳐 수행해 처리량(throughput)을 높이기 위해서다.
    즉 한 명령어가 끝나길 기다리는 게 아니라, 각 단계를 동시에 다른 명령어로 굴려 매 클럭마다 결과가 나오게 하는 구조다.
  • 다만 파이프라인은 hazard(데이터/구조/제어), 분기 예측 실패, 그리고 인터럽트/예외 처리 시 flush/정확한 상태 보장(precise interrupt) 같은 복잡도/비용을 만든다.
    즉 파이프라인은 성능을 올리지만, 인터럽트 처리를 더 까다롭게 만든다.

 

4. 인터럽트가 왜 필요한가

인터럽트는 CPU가 계속 확인(polling)해야 하는 낭비를 줄이고, 우선 처리가 필요한 이벤트를 빠르게 처리하기 위해 필요하다.

  • 인터럽트가 없으면 CPU가 주기적으로 I/O 장치 요청 여부를 확인해야 하고 이는 CPU 리소스를 낭비한다.
  • 인터럽트가 있으면 CPU는 다른 작업을 수행하다가 요청이 들어왔을 때만 처리한다.
  • 인터럽트가 발생하면 CPU는 보통
    1. 현재 실행 상태(PC/FLAGS 등)를 저장
    2. 커널 모드로 전환
    3. 인터럽트 벡터(IVT/IDT)로 핸들러 주소를 찾아 실행
    4. 처리 후 복귀
      의 흐름으로 동작한다.
  • NMI는 일반 인터럽트보다 더 특수하게, 마스크(차단)가 불가능한 성격이라 치명적 이벤트에서 최우선급으로 처리된다.

 

5. 시스템콜(유저 → 커널 전환)이 필요한 이유

시스템콜은 사용자 프로그램이 파일/네트워크/프로세스/메모리 같은 특권 자원을 안전하게 사용하기 위한 “커널 진입 통로”다.

  • 사용자 모드가 직접 하드웨어/커널 자원을 다루면 시스템 안정성/보안이 깨질 수 있다.
  • 그래서 커널만 가능한 작업(특권 명령, 장치 접근, 페이지 테이블 조작 등)은 커널 모드에서만 수행한다.
  • 시스템콜 비용이 드는 이유는
    • 유저→커널 모드 전환 오버헤드,
    • 커널 스택/레지스터 저장 등 컨텍스트 처리,
    • 인자/권한 검증,
    • 유저 버퍼↔커널 버퍼 복사,
    • I/O라면 블로킹/스케줄링까지
      같은 요소가 포함되기 때문이다.

 

6. I/O 3종이 각각 언제 유리한지 (Polling / Interrupt / DMA)

  • Polling(프로그램 I/O, 바쁜 대기): CPU가 주기적으로 장치 상태를 읽어 요청 여부를 확인한다.
    → 일반적으로 CPU 낭비가 크지만,
    • 이벤트가 매우 자주 발생해 인터럽트가 오히려 과부하(인터럽트 폭주)가 되는 경우
    • 아주 짧은 시간만 기다리면 거의 끝나는 경우(지연을 예측 가능하게 관리)
    • 부팅 초기/단순 환경
      에서는 유리할 수 있다.
  • Interrupt I/O: 장치가 준비되면 CPU에 인터럽트를 걸어, CPU는 필요할 때만 처리한다.
    → polling 낭비 감소. 단, 너무 잦은 인터럽트는 오버헤드가 될 수 있다.
  • DMA I/O: CPU는 전송 작업을 직접 하지 않고 DMA(또는 장치)가 메모리와 장치 사이 데이터를 직접 전송한다.
    → CPU는 전송 설정(주소/길이/방향)만 하고, 완료 후 보통 인터럽트로 통지받는다.
    → 대용량 전송에서 CPU 부담을 크게 줄인다. 다만 메모리/버스는 공유 자원이어서 경쟁이 발생할 수 있다.

 

※ 운영에 연결되는 질문 3개 (보완/개선 버전)

  1. API 지연이 튈 때 CPU vs I/O 병목 구분
  • CPU 병목: user/sys CPU↑, run queue↑, context switch↑, iowait 낮음
  • I/O 병목: iowait↑, 디스크 util/큐↑, fsync/flush 대기, DB commit 지연
  • p95/p99는 “증상”이고, 위 지표로 원인을 분리한다.
  1. 스레드가 많아지면 왜 느려질 수 있나
  • 단순히 “스레드가 캐시를 점유해서”라기보다
    컨텍스트 스위칭 비용, 락 경합, 캐시 미스 증가(working set 증가), 스케줄러 큐 증가 때문에 느려질 수 있다.
  • 즉 스레드 수가 증가하면 “일을 더 하는” 게 아니라 “관리 비용과 경합”이 커질 수 있다.
  1. 디스크 쓰기가 느릴 때 fsync/flush는 어디에 걸리나
  • write()는 보통 커널의 페이지 캐시에 먼저 쓰여 빠르게 반환될 수 있다.
  • flush/writeback은 커널이 나중에 디스크로 내려쓰는 과정이다.
  • fsync()는 “지금까지의 변경이 실제 디스크에 안전하게 기록될 때까지 기다려라”이므로
    디스크/스토리지 지연을 정면으로 맞아 여기서 블로킹이 크게 발생한다.
  • DB의 commit 지연(특히 WAL/redo)은 이 fsync와 연결되는 경우가 많다.

※ 소리 내서 2개만 말하기 (보완/개선 버전)

  1. 인터럽트가 없으면
    CPU가 I/O 완료 여부를 계속 확인(polling)해야 해서 낭비가 커지고, 중요한 이벤트 처리도 비효율적이어서 전체 성능과 반응성이 떨어질 수 있다.
  2. DMA가 CPU를 살리는 방법
    PIO/인터럽트 기반 전송에서는 CPU가 데이터 복사 전송에 더 많이 관여할 수 있는데, DMA를 쓰면 CPU는 전송 설정만 하고 실제 데이터 이동은 DMA/장치가 수행한다. 그래서 CPU는 계산/스케줄링 등 다른 작업을 수행할 수 있고, 대용량 I/O에서 성능이 크게 좋아진다.