프로세스의 문맥 교환
프로세스의 문맥 교환(context switch)은 운영체제(Operating System)에서 프로세스(또는 스레드) 간 CPU 사용권을 전환하는 핵심 메커니즘임.
여러 프로세스가 동시에 존재하고, 제한된 수의 CPU 코어(또는 실제로 단 하나의 CPU 코어만)가 있을 때 운영체제는 시간 분할(time-sharing) 기법이나 우선순위 기반 스케줄링, 멀티태스킹 환경을 제공하기 위해 문맥 교환을 수행함.
문맥 이란?
문맥(context)이란 현재 수행 중인 프로세스(또는 스레드)의 상태를 의미함.
구체적으로는 다음과 같은 정보가 포함됨.
1. CPU 레지스터 상태(Register set)
일반 레지스터(General-purpose registers): EAX, EBX, ECX ... (x86 기준), 또는 x0, x1 ... (ARM 64 기준)
프로그램 카운터(Program Counter, Instruction Pointer)
스택 포인터(Stack Pointer)
CPU 플래그(Flags, Condition codes) 등
2. 프로세스 메모리 관련 정보
페이지 테이블(Page Table) 등 메모리 매핑 상태
세그먼트(세그먼테이션을 사용하는 아키텍처라면) 관련 정보
가상 메모리 영역(Virtual Memory Area, VMA) 구조 등
3. 커널 내부 관리 정보
프로세스 제어 블록(PCB, Process Control Block) 또는 태스크 구조체(Task_struct, Linux 기준)에 저장되는 정보
스케줄링 큐(Scheduling queue), 우선순위, 프로세스 상태(준비상태, 대기상태 등)
파일 디스크립터/핸들 테이블 등(주로 문맥 교환 시점에 전부 바뀌는 것은 아니지만, 한 프로세스에서 다른 프로세스의 자원을 참조할 수 없으므로 프로세스 경계가 명확해야 함)
문맥 교환에서 가장 중요한 것은 CPU 레지스터 상태와 프로세스(또는 스레드) 제어와 관련된 운영체제 내부 자료구조를 보존/복원하는 것임.
문맥 교환이 필요한 이유
1. 멀티태스킹(Multitasking) 지원
단일 CPU 환경에서도 여러 개의 프로세스가 교대로 실행되는 것처럼 보이도록 하기 위해 시간 분할 기법(time-slicing)을 사용함.
이를 위해서는 주기적으로 한 프로세스에서 다른 프로세스로 CPU를 넘겨줘야 함.
2. 응답성(Responsiveness) 향상
시스템에서 대기 중인 프로세스(특히 우선순위가 높은 프로세스)가 빠르게 CPU를 할당받아 실행되어야 함.
그 과정에서 현재 CPU를 사용 중인 프로세스의 문맥을 저장한 후, 새 프로세스의 문맥으로 전환해야 함.
3. 프로세스 간 격리(Isolation) 보장
운영체제는 각 프로세스가 자기 고유의 메모리 공간과 자원을 안전하게 사용할 수 있도록 해야 함.
문맥 교환 시점에 CPU와 메모리 관리장치(MMU) 등에서 이전 프로세스의 상태를 완전히 벗어나고, 새 프로세스의 상태(페이지 테이블 등)로 전환함.
문맥 교환의 동작 과정
문맥 교환은 일반적으로 시스템 콜(예: sched_yield(), sleep())이나 하드웨어 인터럽트(타이머 인터럽트, I/O 인터럽트 등)로부터 시작됨.
다음은 일반적인 문맥 교환 절차임.
1. 현재 실행 중인 프로세스의 상태 저장
CPU 레지스터 내용(프로그램 카운터, 스택 포인터, 일반 레지스터, 플래그 등)을 PCB(Task_struct, TCB 등)에 저장.
일부 아키텍처에서는 하드웨어에서 자동으로 진행(예: x86의 특권 레벨 전환 시 자동으로 특정 레지스터를 스택에 푸시)하기도 하고, 일부는 운영체제에서 작성한 문맥 교환 함수(어셈블리 루틴)로 진행.
2. 스케줄러(Scheduler) 실행
운영체제의 스케줄러가 활성화되어 다음에 실행할 프로세스(또는 스레드)를 결정.
우선순위, 준비 리스트(Ready Queue) 상태, 스케줄링 알고리즘(RR, Priority, CFS 등)에 따라 다음 태스크를 결정.
3. 새 프로세스의 문맥 정보 로드
스케줄러가 선택한 프로세스(또는 스레드)의 PCB에서 레지스터, 프로그램 카운터, 스택 포인터, 메모리 맵핑(페이지 테이블) 등을 CPU에 복원.
이때 페이지 테이블(또는 MMU 컨텍스트)을 새 프로세스에 맞게 설정하여 가상 메모리 환경을 전환.
필요 시 TLB(Translation Lookaside Buffer) 플러시가 발생할 수 있음(특히 다른 주소 공간에 진입할 때).
4. 프로세스 실행 재개
복원된 프로그램 카운터(Instruction Pointer) 위치부터 새 프로세스가 실행을 계속 진행.
이후 동일한 방식으로 다음 문맥 교환이 이뤄질 때까지 실행.
문맥 교환은 주어진 스케줄링 정책(예: Round Robin, Priority Scheduling)과 커널 아키텍처 설계(예: monolithic kernel, microkernel, hybrid 등)에 따라 세부 구현이 달라질 수 있음.
문맥 교환의 오버헤드
문맥 교환은 시스템에 추가적인 비용을 발생시킴.
오버헤드의 주요 원인은 다음과 같음.
1. 레지스터 저장 및 복원 비용
CPU 레지스터를 PCB 등에 저장하고 다시 로드하는 과정에서 CPU 사이클이 소모됨.
2. TLB Flush(또는 Context Switch) 비용
다른 프로세스의 주소 공간으로 넘어가면, 가상 주소 → 물리 주소 매핑을 캐싱하는 TLB를 새로 채워야 할 수 있음.
이는 성능 저하를 일으킴.
3. 캐시(Cache) 로컬리티 손실
이전 프로세스가 사용하던 데이터, 명령어가 CPU 캐시에 남아 있어도, 새 프로세스가 전혀 다른 메모리 위치를 참조하면 캐시 미스(cache miss)가 증가함.
4. 커널 스케줄러 및 시스템 호출 처리 비용
스케줄러 코드 실행과 커널 모드 전환(트랩 또는 인터럽트)을 위한 오버헤드가 추가됨.
따라서 너무 잦은 문맥 교환은 전체 시스템 성능을 저하시킬 수 있음.
스케줄링 알고리즘은 이를 고려하여 시간 할당량(time quantum)을 적절히 조정하고, 우선순위 정책을 통해 불필요한 문맥 교환을 방지하려 함.
운영체제별 문맥 교환 구현 예시
1. Linux
리눅스 커널에서 문맥 교환은 schedule() 함수를 중심으로 진행됨.
각 프로세스(태스크)는 task_struct라는 커널 자료구조로 관리됨.
문맥 교환은 일반적으로 “유저 모드 → 커널 모드” 전환 후 스케줄러가 동작하여, 선택된 프로세스의 task_struct에 저장된 레지스터 상태와 메모리 맵핑을 복원함.
아키텍처별로 문맥 교환에 사용되는 어셈블리 루틴(예: x86의 __switch_to)이 구현되어 있으며, 이 루틴이 실제 레지스터 스위칭을 수행함.
2. Windows
Windows의 커널도 유사한 방식으로 Thread 및 Process 객체를 관리하며, 스케줄러(Dispatcher)가 동작함.
Windows에서는 커널 오브젝트(Dispatcher Object)로 각 스레드를 표현하고, 문맥 교환 시 커널 스택, trap frame, KTHREAD 구조체 등이 중요한 역할을 함.
대칭형 멀티프로세서(SMP) 환경에서 각 코어(논리 코어)마다 별도의 스케줄링 큐를 둘 수도 있음.
3. Microkernel (예: Minix, L4 등)
마이크로커널 구조에서는 많은 서비스가 유저 공간에서 동작하므로, 커널 호출이 더 빈번할 수 있고 문맥 교환이 잦을 수 있음.
이때도 기본적인 문맥 교환 메커니즘은 크게 다르지 않지만, 메시지 패싱을 통한 커널 진입/이탈이 많아 오버헤드가 높을 수 있음.
프로세스 스레드와 문맥 교환
프로세스 문맥 교환은 주소 공간 전체를 변경해야 하므로, TLB 플러시 등의 비용이 큼.
스레드 문맥 교환은 같은 프로세스 내 스레드 간 전환 시 주소 공간이 동일하기 때문에, 상대적으로 적은 오버헤드로 스위칭이 가능함(스택, 일부 레지스터만 전환하면 됨).
하지만 커널 레벨 스레드에서 다른 프로세스의 스레드로 문맥이 전환된다면 결국 프로세스 경계를 넘어가게 되므로, 일반 프로세스 문맥 교환 수준의 오버헤드가 발생함.
Lazy Context Switching
일부 시스템에서는 완전한 레지스터 저장/복원을 지연(lazy)시켜서 실제로 필요한 순간에만 수행함.
예를 들어 FPU(부동소수점 연산 장치) 레지스터를 공유하는 기법 등에서 사용함.
이는 빈번한 스위칭이 일어나더라도 실제로 FPU나 SIMD 레지스터를 사용하지 않는 프로세스 간에는 저장/복원을 최소화하여 오버헤드를 줄일 수 있음.
가상화 환경에서의 문맥 교환
하이퍼바이저(Hypervisor) 아래에서 게스트 OS 간 전환 시, VMCS(Virtual Machine Control Structure) 같은 가상화 전용 하드웨어 구조가 사용됨(Intel VT-x, AMD-V 등).
호스트 OS 차원 문맥 교환과 게스트 OS 내부 문맥 교환이 중첩되어 복합적인 오버헤드가 발생할 수 있음.
정리
문맥 교환(context switching)은 멀티태스킹 운영체제에서 필수적인 기능이지만, CPU와 시스템 리소스를 추가적으로 소비하는 오버헤드가 발생함.
따라서 운영체제는 스케줄링 알고리즘과 프로세스/스레드 관리 방식을 통해 문맥 교환 횟수를 적절히 통제하고, 구현 수준에서 하드웨어의 기능(FPU 상태 Lazy 전환, ASID(Address Space Identifier) 지원 등)을 활용하여 오버헤드를 최소화하려고 함.
문맥 교환은 다음과 같은 핵심 포인트를 지님.
1. 상태 보존과 복원: CPU 레지스터와 PCB를 통해 수행 중인 프로세스의 상태를 저장/복원함.
2. 메모리 주소 공간 전환: 페이지 테이블 등 메모리 맵핑이 달라지므로 TLB 플러시가 발생할 수 있음.
3. 성능 오버헤드: 스위칭 비용, 캐시 로컬리티 손실, TLB 재초기화 등이 성능 저하를 일으킴.
4. 설계 최적화: Lazy FPU 스위칭, ASID 활용, 적절한 시간 쿼럼(quantum) 설정으로 오버헤드를 완화함.
이러한 점을 종합하면, 문맥 교환은 멀티프로세싱 및 멀티태스킹 환경을 구현하는 데 있어 필수적이지만, 이를 효율적으로 설계하고 구현하는 것이 운영체제의 중요한 과제임을 알 수 있음.
'Operating System > Computer' 카테고리의 다른 글
[Computer] 로드밸런서 (0) | 2025.01.29 |
---|---|
[Computer] 멀티프로세싱 및 멀티스레딩 (0) | 2025.01.27 |
[Computer] 프로세스와 스레드의 차이 (0) | 2025.01.27 |
[Computer] CPU 스케줄링 알고리즘 (0) | 2025.01.26 |
[Computer] 자바 표준 스펙 (1) | 2025.01.26 |