[운영체제] Context Switching & PCB (Process Control Block)

전윤혁·2024년 8월 29일
0

OS

목록 보기
3/18

Switching Between Processes

이전 글에서 프로세스의 개념과, 생성, 실행 과정을 살펴봤다. 이번 내용에서는 프로세스 간 전환에 대한 내용을 알아보도록 하겠다.


1. PCB (Process Control Block)

프로세스 간 전환에 대해 설명하기 전, 기본적인 개념을 먼저 짚고 넘어가자.

PCB(Process Control Block)란 운영체제에서 각 프로세스에 대한 상태 정보를 저장하고 관리하는 데이터 구조이다.

PCB의 중요한 요소들을 요약하면 아래와 같다.

  • Process ID
    프로세스 식별 ID

  • Process State
    프로세스의 상태
    (running, ready, waiting, terminated 등)

  • Program Counter
    프로세스가 다음에 실행할 명령어의 주소

  • Registers
    프로세스 실행 시점의 CPU 레지스터 값

  • CPU Scheduling Information
    스케줄링과 관련된 정보
    (우선 순위, 최종 실행 시간, CPU 점유 시간 등)

  • Memory management information
    메모리 관리와 관련된 정보
    (프로세스가 사용하는 메모리 주소 공간, 페이지 테이블, 세그먼트 테이블 등)

  • I/O Status
    프로세스가 사용 중인 입출력 장치, 열린 파일, 입출력 요청 정보 등

이전 글에서, exec() 호출 시 현재 프로세스의 PCB가 새로운 프로세스의 것으로 덮어 씌워진다고 설명한 부분을 이제 이해할 수 있을 것이다!


2. Context

Context란 운영체제에서 프로세스가 실행되는 동안, 해당 프로세스에 대한 모든 상태 정보를 말한다.

그렇다면 Context와 PCB는 무슨 차이일까?

PCB는 운영체제가 프로세스를 관리하기 위해 저장하는 정적인 데이터 구조라고 할 수 있고, Context는 CPU가 프로세스를 실행하기 위해 사용하는 실행 시점의 동적 정보라고 할 수 있다.

크게 의미가 없는 비교일 수 있지만, Context는 Context Switching과 연결되는 개념이기 때문에 짚고 넘어가는 것이 찝찝하지 않다.

Context는 "문맥"으로, Context Switching은 "문맥 교환"으로 흔히 해석된다. 하지만 필자는 Context라는 개념을 문맥이라고 해석하는 것이 오히려 이해에 어려움을 준다고 생각하기에, Context라는 단어 그대로 사용하겠다.


3. Context Switching

Context Switching을 말 그대로 해석해보면 Context를 교체/교환하는 것으로 이해할 수 있다. Context Switching이란, 운영체제가 여러 프로세스를 실행할 때 CPU가 한 프로세스에서 다른 프로세스로 전환되는 과정을 의미한다.

Context Switching 과정을 통해 운영체제는 현재 실행 중인 프로세스의 상태를 저장하고, 필요한 시스템 작업을 처리한 후, 다시 원래의 프로세스나 다른 프로세스로 전환하여 실행을 이어가게 된다.

Context Switching과 관련된 내용부터는 다시 OSTEP 책의 설명 흐름을 따라가보자.

LDE (Limited Direct Execution)

책에서는 먼저 LDE 기법에 대해 소개한다.

먼저 Direct Execution에 대해 알아보자. Direct Execution이란, 사용자 프로그램이 운영체제의 개입 없이 직접 CPU에서 실행되는 방식을 의미한다.

Direct Execution의 경우, 위의 실행 흐름처럼 한 번 Entry Point(main 함수)를 통해 프로그램을 실행하면, 프로그램 종료 시까지 멈추지 않고 실행된다.

이는 운영체제의 개입으로 인한 오버헤드가 없기 때문에, 가장 효율적이고 빠르게 프로그램을 실행하는 방식이라고 할 수 있다.

하지만 이 경우 프로그램의 실행에 대해 운영체제가 개입할 틈이 없게 되고, CPU 가상화는 물론, 프로그램 실행에 대한 안정성과 보안을 전혀 보장할 수 없게 된다.

따라서 운영체제에게는 프로세스의 실행을 제어할 수 있는 힘이 필요하고, 이것이 "Limited" Direct Execution 기법이다.

요약하면, 이전 글에서 설명했던 User mode와 Kernel mode의 분리를 통해 민감한 작업을 운영체제가 제어하고, Context Switching을 통해 프로세스 실행에 운영체제가 개입할 수 있게 된다고 할 수 있겠다.

1) Cooperative Approach: Wait For System Calls

그렇다면 어떻게 Context Switching을 수행할 수 있을까?

책에서는 Context Switching을 Cooperative(협조적) 방식과 Non-Cooperative(비협조적) 방식으로 나누어 설명하고 있다.

먼저 Cooperative 방식의 경우, 프로세스가 스스로 CPU를 운영체제에 반환하는 방식으로, 운영체제의 관점에서 매우 간단한 방법이다. 이 방식에서는 프로세스가 주기적으로 시스템 호출을 통해 CPU를 자발적으로 포기하고, 운영체제가 다른 작업을 수행할 수 있도록 제어권을 넘긴다.

사실 필자는 Cooperative가 아니라 Naive(순진한) 라는 표현이 더 맞다는 생각이 든다. 만약 프로세스가 스스로 CPU를 포기하지 않으면, 운영체제가 개입할 방법이 없기 때문이다! 프로세스가 무한 루프에 빠지기라도 하는 날에는 시스템이 멈추고, 기계를 재부팅해야 한다.

2) Non-Cooperative Approach: The OS Takes Control

앞서 설명한 문제점으로 인해 Cooperative 방식은 현대 운영체제에서 사용되지 않는 방법이다. 이제 반대 방식인 Non-Cooperative 방식을 알아보자.

Non-Cooperative 방식은 운영체제가 프로세스의 협력 없이도 CPU의 제어권을 강제로 가져올 수 있는 방식을 의미한다. 이를 위한 중요한 개념이 타이머 인터럽트(Timer Interrupt)이다.

컴퓨터가 부팅될 때, 운영체제는 타이머를 시작한다. 이 타이머는 일정한 시간(밀리초)마다 인터럽트를 발생시킨다.

타이머 인터럽트가 발생하면, 운영체제는 현재 실행 중인 프로세스를 중단하고, 해당 프로세스의 상태를 저장한 후, 미리 설정된 인터럽트 핸들러를 실행한다. 인터럽트 핸들러는 인터럽트가 발생했을 때 운영체제가 수행할 작업(스케줄링, 자원 관리 등)을 정의한 코드이다.

요약하면, Non-Cooperative 방식에서는 타이머와 인터럽트 핸들러를 통해 운영체제가 프로세스로부터 주기적으로 CPU의 제어권을 가져오게 된다.


4. Context 저장 & 복원

인터럽트 핸들러가 실행되면, 운영체제는 현재 프로세스를 계속 실행할지, 다른 프로세스를 실행할지 결정할 수 있다.

이 때, 다른 프로세스를 실행하기로 결정한 경우 Context Switching이 발생하게 된다. Context Switching 과정에서 운영체제는 현재 실행 중인 프로세스의 상태를 저장하고, 다음에 실행할 프로세스의 상태를 복원하는 작업을 수행한다.

해당 과정을 구체적으로 살펴보자.

  • 현재 프로세스의 레지스터 값 저장
    CPU의 일반 목적 레지스터, 프로그램 카운터(PC), 커널 스택 포인터와 같은 중요한 레지스터 값을 현재 프로세스의 커널 스택에 저장한다.

  • 새로운 프로세스의 레지스터 값 복원
    다음으로 실행할 프로세스의 커널 스택에서 해당 프로세스의 레지스터 값을 복원한다. 여기에는 이전에 저장된 일반 목적 레지스터, 프로그램 카운터(PC), 커널 스택 포인터 값이 포함된다.

  • 커널 스택 전환
    운영체제는 CPU가 사용할 커널 스택을 새로 실행할 프로세스의 커널 스택으로 전환한다.

📌 커널 스택이란?

커널 스택은 운영체제가 각 프로세스에 대해 관리하는 스택 공간으로, 프로세스의 시스템 호출 처리, 인터럽트 처리 시 사용된다.


마치며

이번 글에서는 Context Switching에 대해서 알아봤다. 그런데 만약 시스템 콜을 처리하는 동안 인터럽트가 발생하거나, 인터럽트를 처리하는 중 또다른 인터럽트가 발생할 경우에는 어떻게 해야 할까?

이러한 문제점이 이전에 언급했던 동시성(Concurrency) 문제다. 운영체제는 내부 데이터 구조에 대한 동시 접근을 보호하기 위해 다양한 Locking 기법을 사용하는데, 자세한 내용은 동시성 파트에서 알아보도록 하자!

profile
전공/개발 지식 정리

0개의 댓글