-
문서 작성 계기
- Kotlin Coroutine의 메커니즘을 살펴보던 중, 쓰레드 교체 비용에 대한 언급이 있어 이를 이해하고자 함
-
Context Swtiching
- 운영체제가 여러 프로세스나 스레드를 번갈아 실행할 수 있도록, 각각의 상태를 저장하고 복원하는 과정
- 효율적으로 시스템 자원을 분배하고 여러 작업을 동시에 처리하는데 필요한 과정이다.
-
CPU 스케줄링에 의해 프로세스, 혹은 스레드가 교체되는 순간에 이뤄진다.
- CPU 스케줄링
- 운영체제에서 다수의 프로세스가 CPU를 공유할 시, 어떤 프로세스에게 언제 CPU 시간을 할당할지 결정하는 과정
- 효율적으로 CPU 자원을 관리하여 시스템의 응답성, 처리량, 대기 시간 등을 최적화도록 한다.
- 프로세스
- 실행 중인 프로그램으로, 각 프로세스는 CPU 시간과 메모리를 할당받아 독립적으로 실행된다.
- 스레드
- 프로세스 내에서 실행되는 기본적인 작업 단위
- 여러 스레드를 가진 프로세스는 동시에 여러 작업을 할 수 있다.
-
필요성
- CPU는 한 번에 하나의 작업만 처리할 수 있다.
- 여러 프로세스를 동시에 실행하는 것처럼 보이게 하기 위해서는 주기적으로 각 프로세스나 스레드의 상태를 저장하고 다른 작업을 실행한 후, 다시 이전 상태로 복원할 수 있어야 한다.
-
기본 메커니즘
- Context Save
- 현재 프로세스의 상태를 저장하는 과정
- 프로세스나 스레드는 CPU에서 실행되는 동안 특정 상태를 유지하는데, 이러한 상태를 Context라 부른다.
- Context에 대한 상세 내용은 하단에서 후술할 것
- Context Switching이 발생하면 운영체제는 현재 프로세스의 상태를 메모리 내의 프로세스 제어 블록(PCB) 등에 저장한다.
- Context Restore
- 운영체제는 다른 프로세스를 실행한다.
- 이때 해당 프로세스의 상태를 PCB에서 복원한다.
- 다시 말해, 프로세스 레지스터, 프로그램 카운터, 스택 포인터 등을 복구한다.
- 프로세스 실행
- 새로운 프로세스가 복원된 상태를 기반으로 실행된다.
-
빈번한 Context Switching은 성능 저하를 일으킨다.
- 레지스터와 상태를 저장하고 복원하는데 시간이 걸리기 때문
-
Context Switching 비용은 프로세스가 쓰레드보다 더 크다.
- 프로세스 Context Switching은 프로그램 단위로서 자신만의 메모리 공간을 가진다.
- 쓰레드 Context Switching은 프로세스 내의 메모리 공간을 다른 쓰레드와 공유한다.
-
Context Switching의 비용을 낮추려면?
- 스위칭 빈도를 최적화해야 한다.
- 우선순위가 높은 프로세스나 스레드를 먼저 실행하도록 한다.
- 스레드 밀리시클링: 스레드의 실행 시간을 적절히 분배하여 스위칭 비용 최소화
-
Context에 포함되는 정보들은 다음과 같다.
- 레지스터 상태
- CPU의 레지스터 값(예: 프로그램 카운터, 스택 포인터 등)을 의미한다.
- 프로세스가 현재 진행중인 작업을 기억하기 위해 필요하다.
- 메모리 정보
- 프로세스가 사용하고 있던 메모리 영역(스택, 힙 등)의 상태를 포함한다.
- 프로세스 상태
- 실행 중인 프로세스의 상태(대기, 실행 중 등)를 포함한다.
- CPU 스케줄링 정보
- 프로세스가 다음에 실행될 때의 우선순위나 필요한 리소스 등을 포함한다.
-
레지스터
- 레지스터(Register)는 CPU 내부에 위치한 작은 크기의 고속 기억 장치
- CPU가 프로그램을 실행하는 동안 빠르게 접근되고 수정되므로, 메모리보다 속도가 훨씬 빠르다.
- 프로세서가 작업을 수행하는 동안 데이터를 일시적으로 저장하거나 처리하는 데 사용된다.
- 명령어를 가져오고 연산을 처리하는 동안, 레지스터는 그 작업에 필요한 중간 값을 저장하는 역할을 수행한다.
- 예를 들어, 덧셈 연산을 수행할 때, 두 값을 레지스터에 저장하고, 연산을 처리한 후 그 결과를 다시 레지스터에 저장한다.
- Context에 포함되는 대표적인 정보 중 하나로 레지스터 값을 종종 언급한다.
- 이는 CPU가 계산, 주소 지정, 제어 등의 작업을 수행할 때 필요한 정보를 담고 있는 값을 의미한다.
- 레지스터의 종류는 다양하며, 그 목적에 따라 다양한 작업을 처리하는데, 대표적으로 다음의 것들이 있다.
- 프로그램 카운터(Program Counter, PC)
- CPU가 실행해야 할 다음 명령어의 주소를 저장한다.
- 명령어를 순차적으로 실행하기 위해 필요한 레지스터이다.
- 누산기(Accumulator, ACC)
- 연산 결과를 저장하는 레지스터
- 덧셈이나 곱셈 결과를 일시적으로 저장한다.
- 스택 포인터(Stack Pointer, SP)
- 스택의 현재 위치를 가리키는 레지스터
- 함수 호출 시 지역 변수나 반환 주소를 저장하는 데 사용된다.
- 기타 일반 목적 레지스터(General Purpose Registers)
- CPU가 연산에 사용할 수 있는 임시 저장소로, 여러 가지 데이터를 저장할 수 있다.
- 예를 들어, 특정 변수나 계산 중간 결과를 저장하는 데 사용됩니다.
- 플래그 레지스터(Flag Register)
- 연산의 결과에 따라 설정되는 여러 플래그(예: 오버플로우, 제로, 부호 등)가 저장된다.
- 이는 후속 연산에 영향을 줄 수 있다.