문맥 교환(Context Switch)

Elena·2026년 1월 30일
post-thumbnail

1. 문맥 교환(Context Switch)이란?

하나의 CPU 코어가 실행 중인 프로세스(또는 스레드)를 멈추고, 다른 프로세스로 전환할 때 현재 상태를 저장하고 다음 상태를 불러오는 과정

Context(문맥): CPU가 해당 프로세스를 실행하기 위해 필요한 정보들(레지스터 값, Program Counter, Stack Pointer 등) 이 정보들은 PCB(Process Control Block)에 저장된다.

2. 왜 일어날까?

CPU는 한 번에 하나의 작업만 할 수 있지만, 여러 프로그램이 동시에 돌아가는 것처럼 느끼는 것은 CPU가 아주 짧은 시간 동안 여러 프로세스를 번갈아 가며 실행하기 때문이다.

  • 멀티태스킹: 할당된 시간(Time Quantum)을 모두 썼을 때
  • 인터럽트 발생: 입출력(I/O) 요청이 오거나 시스템 콜이 발생했을 때
  • 대기: 프로세스가 실행 중에 입출력 완료를 기다려야 할 때

3. 진행 과정

프로세스 A에서 B로 전환되는 시나리오

  1. A 정지: 실행 중인 프로세스 A에 인터럽트나 시스템 콜이 발생
  2. 상태 저장: CPU의 레지스터에 있던 A의 현재 작업 데이터를 PCB_A에 저장
  3. 다음 프로세스 선택: 스케줄러가 다음에 실행할 프로세스 B를 선택
  4. 상태 복원: PCB_B에 저장되어 있던 B의 이전 작업 데이터를 CPU 레지스터로 불러옴
  5. B 실행: 프로세스 B가 중단되었던 지점부터 다시 실행

4. 오버헤드(Overhead)

문맥 교환은 사실 공짜가 아니다. 상태를 저장하고 복원하는 동안 CPU는 실제 유용한 계산 작업을 하지 못하는데 이를 오버헤드라고 한다.
문맥 교환이 너무 자주 일어나면 배보다 배꼽이 더 커져서 시스템 성능이 떨어질 수 있다.

최근 공부했던 코루틴(Coroutine)이나 스레드(Thread)와 연결해서 생각본다면?

  • 프로세스 vs 스레드: 프로세스 간 문맥 교환보다 스레드 간 문맥 교환이 더 빠르다. 스레드는 스택을 제외한 메모리 영역을 공유하기 때문.

  • 코루틴: 코루틴은 OS가 개입하는 '커널 수준의 문맥 교환'이 아니라, 애플리케이션 레벨에서 제어권을 넘기기 때문에 오버헤드가 훨씬 적다.

구분프로세스 문맥 교환스레드 문맥 교환
공유 영역거의 없음 (독립된 주소 공간)스택 제외 데이터/힙 영역 공유
메모리 주소 전환가상 메모리 주소(MMU)를 통째로 바꿔야 함주소 공간을 그대로 유지
TLB 비우기캐시의 일종인 TLB를 완전히 비워야 함(Flush)TLB를 비울 필요가 없음
비용매우 높음상대적으로 낮음

TLB(Translation Lookaside Buffer)란?
가상 주소를 물리 주소로 변환하는 정보를 담은 일종의 주소 변환 캐시. 프로세스가 바뀌면 주소 체계 자체가 달라지므로 이 캐시를 다 지워야 하는데, 이것이 프로세스 문맥 교환의 가장 큰 오버헤드 중 하나

3. 문맥 교환을 줄이기 위한 노력

  • 배치 처리 (Batch Processing): 작업을 하나씩 처리하지 않고 모아서 한꺼번에 처리해 교환 횟수를 줄인다.

  • 비동기 I/O (Non-blocking I/O): I/O 대기 시간 동안 프로세스를 Waiting 상태로 보내지 않고 다른 일을 하게 함으로써 불필요한 문맥 교환을 방지한다.

  • 유저 레벨 스레드/코루틴: 운영체제 커널이 개입하지 않고 애플리케이션 수준에서 실행 흐름을 바꾸어 오버헤드를 극단적으로 낮춘다.

자바(Java)나 코틀린(Kotlin)에서 사용하는 일반적인 Thread는 보통 커널 레벨 스레드와 1:1로 매핑된다. 하지만 최근 주목받는 Java의 Project Loom(Virtual Thread)이나 Kotlin Coroutine이 바로 이 유저 레벨 스레드의 개념을 현대적으로 발전시켜 단점(I/O 블로킹 등)을 해결한 형태이다.

4. 문맥 교환에 따른 프로세스 상태 전이

문맥 교환은 주로 두 가지 경로를 통해 일어난다.
1) "잠시 비켜주세요" (Running → Ready)

  • 원인: 할당된 시간(Time Quantum)이 끝났을 때 (Preemption)
  • 상태 변화: CPU를 강제로 반납하고 다시 Ready 상태로 돌아가 줄의 맨 뒤로 간다.
  • 문맥 교환: 이때 현재까지의 작업 내용을 PCB에 저장

2) "결과 나올 때까지 쉬다 올게요" (Running → Waiting)

  • 원인: 실행 중 I/O 요청(예: DB 쿼리 실행 후 응답 대기)이 발생했을 때
  • 상태 변화: CPU가 있어도 일을 못 하므로 Waiting 상태로 들어간다.
  • 문맥 교환: CPU는 노는 꼴을 못 보므로, 즉시 다른 Ready 상태의 프로세스를 꺼내 Running으로 바꾼다.
  • 복귀: I/O가 완료되면 다시 Ready 줄로 돌아가 자기 차례를 기다립니다.
  • Ready (준비): CPU를 할당받기 위해 줄을 서서 기다리는 상태. 메모리에 로드되어 실행 준비를 마쳤지만, CPU가 다른 일을 하고 있는 상황
  • Running (실행): CPU를 할당받아 실제로 명령어를 처리하고 있는 상태
  • Waiting / Blocked (대기/차단): I/O 작업(파일 읽기, 네트워크 응답 등)이나 특정 이벤트가 발생하기를 기다리는 상태. 이때 CPU는 이 프로세스를 붙잡고 있지 않고 다른 프로세스로 넘겨버림
profile
一切唯心造

0개의 댓글