지나공 : 지식을 나누는 공간
Context Switching 이 비용이 드는 이유 본문
들어가는 말
최근에 컨텍스트 스위칭이 비용이 드는 건 아는데, 왜 비용이 드는건지를 설명해보라는 질문에 간단명료하게 답하지 못했다. 학부 때나 취준하면서 CS를 보기는 했지만 OS, 네트워크 보다도 나도 모르게 프로젝트 과정에 대한 질문에 치우쳐서 학습했던 것 같다. 이를 반성하며... 오래된 OS 책을 다시 꺼냈다. 지금 보니 느낌이 좀 다른데 아무튼 컨텍스트 스위칭에 필요한 배경지식부터 간단하게 리마인드 해본다.
프로세스의 구조
프로세스는 실행 중인 프로그램이고 디스크에 있던 프로그램이 메모리에 로드되면 프로세스가 된다. 이는 Context와 Memory로 개념을 나눌 수 있고, OS는 Context를 저장해서 실행 상태를 관리하고, Memory 구조를 통해 코드, 데이터, 스택, 힙을 분리해서 프로그램을 실행한다.
- Context
- 하드웨어 Context - 레지스터, PC(Program Counter), SP(Stack Pointer)
- PCB(Process Control Block) - PID, 상태, 우선순위
- 메모리 Context - 코드, 데이터, 힙, 스택
- Memory
- 스택
- 힙
- 데이터
- 코드
프로세스 Context: 1) 하드웨어 Context
레지스터
레지스터는 CPU가 프로세스를 처리할 때 필요한 정보를 임시 저장하여 연산 속도를 높이는 초고속 메모리다. 실행할 명령어, 즉 코드 부분의 주소를 가리키기도 하고 연산 결과의 상태를 저장하기도 하고 여러가지 목적에 따라 종류가 나뉜다.
PC (Program Counter)
CPU가 다음에 수행될 명령어의 주소를 저장하는 레지스터다. 명령어가 실행될 때마다 PC가 증가되어 다음 명령어 주소로 업데이트 된다.
SP (Stack Pointer)
현재 스택의 최상단을 가리키는 레지스터로, 스택 메모리에서 가장 최근에 저장된 데이터의 주소를 갖는다. 스택이 함수 호출이나 지역 변수, 리턴 주소 등을 저장하는 메모리 영역이므로, SP는 이에 따라 데이터가 추가되거나 변경될 때마다 업데이트된다.
다만 아래 그림에서처럼 스택은 높은 주소에서 시작했다가 데이터가 추가될 때마다 낮은 주소로 이동하여 주소값이 감소한다. 반면 힙은 커질 때 낮은 주소에서 높은 주소로 이동한다. 이처럼 스택이 특이하게도(?) 데이터가 추가될 때 더 낮은 주소로 이동하는 이유를 알아보니 데이터 증가 시 힙과 메모리 충돌을 방지하기 위함이라고 한다.
프로세스 Context: 2) PCB
PCB
운영체제가 각 프로세스를 관리하기 위해 사용하는 데이터 구조로, 아래 정보를 포함한다.
- PID : 프로세스 고유 식별번호
- 프로세스 상태: Running, Waiting, Ready 등
- 우선순위: 스케줄링에 적용되어야 할 프로세스 우선순위
- CPU 문맥: 레지스터, PC, SP 등
- 메모리 정보: 코드, 데이터, 힙, 스택 등의 메모리 영역
- 입출력 정보: 열린 파일 목록
- 부모 프로세스 ID
// PCB 예시
PID: 1234
상태: Ready
PC: 0x100A
SP: 0x2000
열린 파일: /home/user/file.txt
프로세스 Context: 3) Memory Context
프로세스가 사용하는 메모리 구조에 대한 정보를 의미한다. 메모리 내에서 낮은 주소 ~ 높은 주소에 위치한 영역 순으로 작성하면 아래와 같다.
- 코드 영역: 실행할 명령어를 저장
- 데이터 영역: 전역변수, static 변수 저장
- 힙 영역: 동적 할당된 메모리
- 스택 영역: 지역변수, 함수 호출 정보 저장
프로세스 Context - 4) File Context
열려 있는 파일 목록이나, 파일 내에서 현재 읽고 있는 위치, 파일에 대한 읽고 쓰는 권한 등을 저장한다.
MMU (Memory Management Unit) 과 가상메모리
가상 메모리
프로세스가 자신만의 독립적인 메모리 공간을 가지는 것처럼 보이게 하는 기술이다. 실제 물리 메모리는 한정적이지만 프로세스에게 가상 메모리 주소를 주고 독립적인 메모리 공간을 갖도록 하여, 프로세스 간의 간섭을 방지한다. 가상 메모리 시스템을 통해 동적으로 할당하거나 회수하면서 메모리를 관리할 수도 있다.
MMU
가상 메모리 시스템을 물리 메모리 주소로 변환하는 장치다. 프로세스가 가상 주소를 사용해서 메모리를 참조하면, MMU는 이를 물리 주소로 변환한다. 이때 Page Table 이라고 불리는 가상주소와 물리주소를 연결하는 매핑 테이블을 통해 물리주소로 변환한다.
- PageTable: 물리주소 - 가상주소 매핑 테이블이고, 각 프로세스가 자신만의 Page Table을 독립적으로 갖는다. 페이징이 아니라 세그멘테이션 메모리 할당 방식이라면 세그먼트 테이블이라고 불리는데 주요 역할이 매핑이라는 점은 동일하다.
- TLB (Traslation Lookaside Buffer) : MMU 내에 존재하는 캐시 메모리로, 최근에 변환된 주소 정보를 빠르게 조회해서 주소 변환 속도를 높인다.
- 페이지 폴트 처리 - CPU가 접근하려는 페이지가 메모리에 없어 page table에서 valid bit 가 0이라면 page fault가 발생하는데, 이때 CPU에 인터럽트 신호를 보내어 디스크를 탐색하게 한다.
가상 메모리, MMU 사용 이유
- 프로세스 격리 : 프로세스가 각자의 페이지 테이블을 통해 각자의 메모리 공간을 갖도록 하여 프로세스 간 간섭을 방지한다.
- 메모리 보호: 각 프로세스가 다른 프로세스의 메모리를 침범하지 않도록 보호한다.
Context Switching 과정, 비용 발생 이유
Context Switching은 CPU가 실행중인 프로세스의 상태, 즉 Context를 저장하고, 다른 프로세스로 전환하는 과정이다.
Context Switching 과정
- 현재 실행 중인 프로세스의 context 저장
- PC (Progrom Counter) 저장
- Register 저장
- SP (Stack Pointer) 저장
- MMU 페이지 테이블 정보 저장
- 새로운 프로세스로 전환
- CPU 스케줄러가 다음 실행할 프로세스를 선택
- MMU 페이지 테이블 교체. 새 프로세스의 페이지 테이블로 설정
- 새로운 프로세스의 Context 복원
- 새로운 프로세스의 PC, 레지스터, SP, MMU 설정 등을 복원
- 새 프로세스의 실행 재개
즉, CPU 의 레지스터를 저장하고 복구해야 하고, 새 프로세스가 실행될 때 MMU 페이지 테이블도 다시 로드해야 하며, 이에 따라 TLB 캐시도 무효화되어 기존보다 성능 저하가 발생한다. 이전 프로세스의 정보가 캐시에 남아있지만 모두 무효화 되므로 속도 저하가 발생한다. 또한, Context Switching은 커널 모드에서 수행되기 때문에 유저모드 -> 커널모드 전환 -> 유저모드로 다시 전환 되므로 이 점에서도 비용이 발생한다.
Context Switching 을 줄이려면
- 스레드를 활용한다면, 스레드는 같은 프로세스 내에서 실행되므로 MMU 페이지 테이블 변경이나 위에서 말한 context 저장 및 복원 과정이 필요 없어서 더 효율적이다.
- CPU 작업과 I/O 작업을 잘 배분하여 불필요한 프로세스 전환을 방지해야 한다.
참고자료)
- 운영체제 내부 구조 및 설계 원리 제 8판
- https://hyem2.tistory.com/entry/%EC%8A%A4%ED%83%9D%ED%8F%AC%EC%9D%B8%ED%84%B0