2025-09-12 00:00
- 
프로세스란 실행 중인 프로그램으로, 운영체제에서 작업의 기본 단위다.
 - 
프로세스는 독립된 메모리 공간(코드, 데이터, 힙, 스택)을 가지며, 그 상태는 PCB(프로세스 제어 블록)를 통해 관리된다.
 - 
운영체제는 문맥 교환을 통해 여러 프로세스를 빠르게 번갈아 실행하며 다중 작업을 구현한다.
 
컴퓨터를 켜고 웹 브라우저를 열어 음악을 들으며 문서를 작성하는 일. 우리에게는 너무나도 당연한 이 동시 작업의 비밀은 바로 ‘프로세스’에 있습니다. 프로세스는 현대 운영체제의 심장과도 같은 핵심 개념으로, 우리가 컴퓨터와 상호작용하는 모든 순간에 관여합니다. 이 핸드북은 프로세스가 왜 만들어졌는지부터 시작하여 그 구조와 작동 방식, 그리고 더 나아가 스레드와의 차이점까지, 프로세스의 모든 것을 쉽고 깊이 있게 파헤쳐 봅니다.
1. 들어가며: 프로세스는 왜 필요했을까?
컴퓨터 과학의 많은 위대한 발명이 그렇듯, 프로세스 역시 ‘비효율’을 개선하려는 노력에서 탄생했다.
컴퓨터 초창기: 한 번에 하나의 작업만
초기 컴퓨터 시스템은 매우 원시적이어서 한 번에 단 하나의 프로그램만 실행할 수 있었다. 이를 ‘일괄 처리(Batch Processing) 시스템’이라 부른다. 사용자가 작업을 제출하면, 컴퓨터는 그 작업이 완전히 끝날 때까지 다른 어떤 일도 할 수 없었다. 만약 프로그램이 프린터의 출력을 기다리거나 사용자의 입력을 기다리는 등 CPU를 사용하지 않는 순간이 오면, CPU는 그저 아무 일도 하지 않고 놀고 있어야만 했다. 값비싼 컴퓨터 자원이 심각하게 낭비되는 순간이었다.
다중 작업의 필요성 대두
컴퓨터의 성능이 발전하면서 이러한 비효율은 더욱 두드러졌다. “CPU가 잠시 쉴 때 다른 프로그램을 실행하면 어떨까?”라는 아이디어가 자연스럽게 등장했다. 여러 프로그램을 메모리에 올려놓고, CPU가 하나의 프로그램에서 대기 상태에 빠지면, 그 즉시 다른 프로그램으로 전환하여 작업을 계속하는 방식. 이것이 바로 ‘다중 프로그래밍(Multi-programming)‘의 시작이었다.
이를 구현하기 위해서는 단순히 프로그램을 메모리에 올리는 것만으로는 부족했다. 각 프로그램이 어디까지 실행되었는지, 어떤 메모리를 사용하고 있는지, 어떤 파일을 열고 있는지 등의 모든 상태 정보를 독립적으로 추적하고 관리할 수 있는 새로운 단위가 필요했다.
프로세스의 탄생: 동시성의 시작
이러한 필요에 의해 탄생한 개념이 바로 **프로세스(Process)**다. 운영체제는 각 프로그램을 독립적인 프로세스로 만들어 관리하기 시작했다. 이로써 여러 개의 프로세스가 짧은 시간 간격으로 번갈아 가며 CPU를 점유하는 ‘시분할 시스템(Time-sharing System)‘이 가능해졌고, 사용자는 마치 여러 프로그램이 동시에 실행되는 것처럼 느끼게 되었다. 이것이 우리가 아는 현대적인 ‘다중 작업(Multitasking)‘의 시작이다.
2. 프로세스란 무엇인가? 개념 정의
가장 흔한 오해 중 하나는 프로그램과 프로세스를 동일시하는 것이다. 둘은 명확히 다르다.
- 
프로그램(Program): 특정 작업을 수행하기 위해 작성된 코드의 묶음. 하드 디스크나 SSD에 저장된, 실행 가능한 파일 상태다. 그 자체로는 생명이 없는 정적인 코드 덩어리다.
 - 
프로세스(Process): 프로그램이 실행되어 메모리에 올라온 동적인 상태. 즉, ‘실행 중인 프로그램’이다. 프로세스는 자신만의 메모리 공간, 자원, 그리고 실행 상태를 가진다.
 
가장 쉬운 비유는 ‘레시피’와 ‘요리’다. **레시피(프로그램)**는 요리를 만드는 방법에 대한 정적인 설명서에 불과하다. 하지만 당신이 주방에서 그 레시피를 보고 재료를 다듬고, 불을 켜고, 조리를 시작하는 행위, 즉 **요리(프로세스)**는 생동감 있는 동적인 활동이다. 하나의 레시피로 여러 번 요리할 수 있듯이, 하나의 프로그램으로 여러 개의 프로세스(예: 웹 브라우저 창을 여러 개 띄우는 것)를 생성할 수 있다.
3. 프로세스의 구조: 메모리 들여다보기
프로세스가 생성되면 운영체제는 해당 프로세스만을 위한 독립적인 메모리 공간을 할당한다. 이 공간은 일반적으로 다음과 같은 네 개의 주요 영역으로 나뉜다.
- 
코드(Code) 또는 텍스트(Text) 영역
- 
실행할 프로그램의 기계어 코드가 저장되는 공간이다.
 - 
이 영역은 읽기 전용(Read-Only)으로 설정되어, 프로세스가 실행 중에 자신의 코드를 수정하는 것을 방지한다.
 - 
여러 프로세스가 같은 프로그램을 실행할 경우, 이 코드 영역은 메모리에서 공유될 수 있다.
 
 - 
 - 
데이터(Data) 영역
- 
프로그램의 전역 변수(Global variables)와 정적 변수(Static variables)가 저장되는 공간이다.
 - 
이 변수들은 프로그램이 시작될 때 할당되어 프로그램이 종료될 때까지 유지된다.
 - 
초기화된 데이터는 BSS(Block Started by Symbol) 세그먼트와 구분되어 관리되기도 한다.
 
 - 
 - 
힙(Heap) 영역
- 
프로그래머가 직접 관리하는 메모리 공간으로, 동적 메모리 할당이 일어나는 곳이다.
 - 
C언어의
malloc()이나 C++의new연산자가 바로 이 힙 영역에 메모리를 할당한다. - 
힙은 메모리의 낮은 주소에서 높은 주소 방향으로 자란다.
 - 
사용이 끝난 메모리는 프로그래머가 명시적으로 해제해야 하며(예:
free(),delete), 그렇지 않으면 메모리 누수(Memory Leak)가 발생할 수 있다. 
 - 
 - 
스택(Stack) 영역
- 
함수의 호출과 관련된 정보가 저장되는 공간이다.
 - 
함수의 매개변수, 지역 변수, 리턴 주소 등이 여기에 저장된다.
 - 
함수가 호출되면 스택에 하나의 프레임(Stack Frame)이 쌓이고, 함수 실행이 끝나면 해당 프레임은 스택에서 제거된다.
 - 
스택은 메모리의 높은 주소에서 낮은 주소 방향으로 자라며, 컴파일러에 의해 자동으로 관리된다. 힙과 스택 영역이 서로를 침범하면 오버플로우가 발생한다.
 
 - 
 
4. 프로세스의 생애 주기: 태어나고, 일하고, 잠들고, 사라지다
프로세스는 생성부터 소멸까지 여러 상태를 거친다. 이를 ‘프로세스 상태 전이’라고 한다.
- 
생성(New): 프로세스가 막 생성된 상태. 운영체제가 해당 프로세스를 위한 각종 자료구조(예: PCB)를 만들고 있지만, 아직 메모리에 완전히 올라오지는 않았다.
 - 
준비(Ready): 프로세스가 메모리에 적재되어 CPU를 할당받기를 기다리는 상태. CPU만 있으면 언제든 실행될 수 있는 상태의 프로세스들이 준비 큐(Ready Queue)에서 대기한다.
 - 
실행(Running): 프로세스가 CPU를 할당받아 명령어를 실제로 실행하고 있는 상태. 시스템에는 CPU 코어의 수만큼만 실행 상태의 프로세스가 존재할 수 있다.
 - 
대기(Waiting 또는 Blocked): 프로세스가 실행 도중 입출력(I/O) 작업이나 특정 이벤트(예: 파일 읽기 완료, 다른 프로세스의 응답)를 기다려야 할 때 들어가는 상태. 이 상태의 프로세스는 CPU를 할당해 줘도 당장 작업을 수행할 수 없다.
 - 
종료(Terminated): 프로세스가 실행을 완료하고 메모리에서 정리되는 상태. 운영체제는 해당 프로세스가 사용하던 모든 자원을 회수한다.
 
5. 운영체제의 매니저, 프로세스 제어 블록(PCB)
운영체제는 수많은 프로세스를 어떻게 구별하고 관리할까? 바로 프로세스 제어 블록(Process Control Block, PCB) 덕분이다. PCB는 운영체제가 각 프로세스를 관리하기 위해 필요한 모든 정보를 담고 있는 핵심 자료구조다. 흔히 ‘프로세스의 명찰’ 또는 ‘프로세스의 주민등록증’에 비유된다.
PCB는 프로세스가 생성될 때 함께 만들어지며, 커널 메모리 공간에 저장된다. 다음은 PCB에 저장되는 주요 정보다.
| 정보 유형 | 설명 | 
|---|---|
| 프로세스 ID (PID) | 각 프로세스를 고유하게 식별하기 위한 번호 | 
| 프로세스 상태 | 현재 프로세스가 준비, 실행, 대기, 종료 중 어떤 상태에 있는지를 나타낸다. | 
| 프로그램 카운터 (PC) | 이 프로세스가 다음에 실행해야 할 명령어의 메모리 주소를 가리킨다. | 
| CPU 레지스터 | 누산기, 인덱스 레지스터 등 이전 실행 시점의 레지스터 값들을 저장한다. | 
| CPU 스케줄링 정보 | 프로세스의 우선순위, 스케줄링 큐에 대한 포인터 등 스케줄링에 필요한 정보 | 
| 메모리 관리 정보 | 베이스 및 한계 레지스터 값, 페이지 테이블, 세그먼트 테이블 등 메모리 정보 | 
| 계정 정보 | CPU 사용 시간, 실제 사용 시간, 시간 제한 등 | 
| 입출력 상태 정보 | 프로세스에 할당된 입출력 장치, 열려 있는 파일 목록 등 | 
6. 마법 같은 동시 실행의 비밀, 문맥 교환(Context Switching)
단일 코어 CPU에서 여러 프로세스가 동시에 실행되는 것처럼 보이는 이유는 운영체제가 매우 짧은 시간 동안 여러 프로세스를 번갈아 가며 실행하기 때문이다. 이때 한 프로세스에서 다른 프로세스로 CPU 제어권을 넘겨주는 과정을 **문맥 교환(Context Switching)**이라고 한다.
문맥 교환의 과정은 다음과 같다.
- 
실행 중인 프로세스 A에게 인터럽트(Interrupt)가 발생한다 (예: 할당된 시간 종료, I/O 요청).
 - 
운영체제는 프로세스 A의 현재 실행 상태(문맥)를 PCB A에 저장한다. (프로그램 카운터, 레지스터 값 등)
 - 
운영체제는 다음에 실행할 프로세스 B를 스케줄링 알고리즘에 따라 선택한다.
 - 
운영체제는 PCB B에 저장되어 있던 프로세스 B의 문맥을 CPU 레지스터 등으로 복원한다.
 - 
프로세스 B가 이전에 중단되었던 지점부터 실행을 재개한다.
 
이 과정은 매우 빠르게 일어나지만, 결코 공짜는 아니다. 문맥을 저장하고 복원하는 데 CPU 시간을 소모하는데, 이를 **오버헤드(Overhead)**라고 한다. 문맥 교환이 너무 잦으면 오버헤드로 인해 실제 작업에 사용되는 시간보다 문맥 교환에 낭비되는 시간이 더 커져 시스템 전체 성능이 저하될 수 있다.
7. 심화 학습: 프로세스와 스레드의 차이
프로세스가 등장하며 다중 작업은 가능해졌지만, 한계도 명확했다. 프로세스 생성은 PCB 생성, 메모리 공간 할당 등 많은 자원과 시간을 필요로 하는 무거운 작업이었다. 또한, 독립적인 메모리 공간 때문에 프로세스 간 데이터 공유가 복잡했다(IPC 필요).
이러한 단점을 보완하기 위해 등장한 개념이 바로 **스레드(Thread)**다. 스레드는 ‘프로세스 내의 실행 흐름 단위’로, ‘경량 프로세스(Lightweight Process)‘라고도 불린다.
하나의 집에 여러 명의 일꾼을 비유로 들어보자.
- 
프로세스: 독립된 ‘집’이다. 각 집은 자신만의 주방, 화장실, 침실(자원)을 가진다.
 - 
스레드: 한 집(프로세스) 안에 사는 ‘가족 구성원’ 또는 ‘일꾼’이다. 이들은 주방과 화장실(코드, 데이터, 힙 영역)을 공유하면서 각자 자신의 방(스택 영역)에서 다른 일을 할 수 있다.
 
| 구분 | 프로세스 (Process) | 스레드 (Thread) | 
|---|---|---|
| 정의 | 실행 중인 프로그램, 자원 할당의 단위 | 프로세스 내의 실행 흐름, CPU 할당의 단위 | 
| 메모리 구조 | 독립적인 메모리 공간 (코드, 데이터, 힙, 스택) | 스택 영역을 제외한 코드, 데이터, 힙 영역을 같은 프로세스 내 다른 스레드와 공유 | 
| 자원 공유 | 원칙적으로 공유하지 않음 (IPC를 통해 통신) | 같은 프로세스 내 자원을 쉽게 공유 가능 | 
| 생성/전환 비용 | 생성 및 문맥 교환 비용이 크다. | 생성 및 문맥 교환 비용이 작다. | 
| 안정성 | 한 프로세스의 오류가 다른 프로세스에 영향을 주지 않음. | 한 스레드의 오류(예: 메모리 침범)가 전체 프로세스에 영향을 미쳐 종료될 수 있음. | 
8. 프로세스 간의 소통, IPC (Inter-Process Communication)
프로세스는 독립적인 존재지만, 때로는 협력해야 할 필요가 있다. 이때 프로세스 간 데이터를 주고받는 통신 방법이 필요한데, 이를 **IPC(프로세스 간 통신)**라고 한다. IPC는 커널의 도움을 받아 이루어지며, 주요 기법은 다음과 같다.
- 
파이프(Pipe): 두 프로세스 간 단방향 통신을 지원하는 간단한 방법.
 - 
메시지 큐(Message Queue): 메시지 단위로 데이터를 주고받으며, 비동기 통신이 가능하다.
 - 
공유 메모리(Shared Memory): 특정 메모리 공간을 여러 프로세스가 공유하여 가장 빠른 통신 속도를 제공한다.
 - 
소켓(Socket): 네트워크 통신을 위해 만들어졌으며, 같은 컴퓨터 내의 다른 프로세스와도 통신할 수 있다.
 
9. 맺음말: 모든 컴퓨터 작업의 기초
프로세스는 단순히 실행 중인 프로그램을 넘어, 운영체제가 자원을 효율적으로 관리하고 사용자에게 원활한 다중 작업 환경을 제공하기 위한 핵심적인 추상화 개념이다. 우리가 워드 프로세서로 문서를 작성하면서 동시에 웹 브라우저로 정보를 검색하고 음악을 들을 수 있는 것은, 운영체제가 이 모든 작업을 별개의 프로세스로 만들어 눈에 보이지 않을 만큼 빠르게 전환하며 관리해주기 때문이다. 프로세스의 개념을 이해하는 것은 컴퓨터가 어떻게 작동하는지 그 근본 원리를 이해하는 첫걸음이라 할 수 있다.
- 
운영체제는 프로세스라는 실행 단위로 프로그램을 관리하며, 이를 통해 동시 다발적인 작업 처리가 가능해진다.
 - 
프로세스는 코드, 데이터, 스택, 힙 메모리 영역으로 구성되며, 프로세스 제어 블록(PCB)을 통해 모든 정보가 관리된다.
 - 
프로세스는 생성, 준비, 실행, 대기, 종료의 5가지 상태를 거치며, CPU 스케줄러에 의해 효율적으로 제어되고 컨텍스트 스위칭을 통해 다중 작업이 이루어진다.
 
프로세스 완벽 핸드북 운영체제의 심장을 파헤치다
우리가 컴퓨터를 켜고 웹 브라우저를 실행하고, 음악을 들으며 문서를 작성하는 이 모든 행위는 운영체제(OS)의 정교한 관리하에 이루어진다. 그 중심에는 바로 **프로세스(Process)**라는 개념이 있다. 프로세스는 현대 컴퓨팅의 동시성, 즉 멀티태스킹을 가능하게 하는 핵심적인 요소다. 이 핸드북은 운영체제의 심장이라 할 수 있는 프로세스의 탄생 배경부터 구조, 작동 방식, 그리고 심화 개념까지 모든 것을 깊이 있게 탐구한다.
1장 프로세스는 왜 탄생했는가
초창기 컴퓨터는 한 번에 단 하나의 작업만을 수행할 수 있었다. 하나의 프로그램이 시작되면 그 프로그램이 완전히 끝날 때까지 다른 어떤 작업도 할 수 없었다. 이는 마치 요리사가 하나의 요리를 완성하기 전까지는 다른 어떤 재료 손질도 할 수 없는 것과 같았다. 이러한 방식은 컴퓨터의 처리 능력(CPU)을 심각하게 낭비했다. 예를 들어, 프로그램이 사용자의 입력을 기다리거나 프린터로 출력하는 동안 CPU는 아무 일도 하지 않고 그저 기다려야만 했다.
컴퓨터 과학자들은 이 비효율을 해결하고자 했다. “CPU가 놀고 있는 시간에 다른 프로그램을 실행시킬 수는 없을까?” 이 질문에서 **멀티프로그래밍(Multi-programming)**과 시분할 시스템(Time-sharing system) 개념이 탄생했고, 이를 구현하기 위한 핵심적인 운영 단위가 바로 프로세스다.
프로세스는 단순히 실행 중인 프로그램을 넘어, 운영체제가 자원을 할당하고 스케줄링하는 기본 단위로 정의된다. 여러 개의 프로세스를 메모리에 동시에 올려두고, CPU는 아주 짧은 시간 간격으로 이 프로세스들을 번갈아 가며 실행한다. 이 전환 속도가 워낙 빨라 사용자 입장에서는 마치 여러 프로그램이 동시에 실행되는 것처럼 느끼게 되는 것이다.
결론적으로 프로세스는 CPU의 활용률을 극대화하고, 사용자에게 **동시에 여러 작업을 수행하는 듯한 경험(멀티태스킹)**을 제공하기 위해 탄생한 운영체제의 위대한 발명품이다.
2장 프로세스 해부학 구조와 핵심 요소
프로그램이 하드 디스크에 저장된 정적인 코드 덩어리라면, 프로세스는 그 프로그램에 생명을 불어넣어 메모리 위에서 살아 움직이는 동적인 존재다. 이 동적인 존재는 어떤 구조로 이루어져 있을까?
프로세스의 메모리 구조
프로세스 하나는 운영체제로부터 독립된 메모리 공간을 할당받는다. 이 공간은 크게 네 가지 영역으로 나뉜다.
| 영역 (Region) | 설명 | 특징 | 
|---|---|---|
| 코드 (Code/Text) | 실행할 프로그램의 코드(기계어)가 저장되는 영역 | 읽기 전용(Read-only), 여러 프로세스가 공유 가능 | 
| 데이터 (Data) | 전역 변수(Global variables)와 정적 변수(Static variables)가 저장되는 영역 | 프로그램 시작 시 할당, 종료 시 소멸 | 
| 힙 (Heap) | 프로그래머가 동적으로 할당하는 메모리 공간 (malloc, new 등으로 할당) | 런타임(실행 중)에 크기 변경 가능, 낮은 주소에서 높은 주소로 자람 | 
| 스택 (Stack) | 함수 호출 시 사용되는 지역 변수(Local variables), 매개변수, 반환 주소 등이 저장되는 영역 | 함수 호출 시 생성, 종료 시 소멸, 높은 주소에서 낮은 주소로 자람 | 
이처럼 각 프로세스는 자신만의 독립적인 메모리 영역을 가지기 때문에, 한 프로세스가 다른 프로세스의 메모리 공간을 함부로 침범할 수 없다. 이는 시스템의 안정성을 보장하는 중요한 메커니즘이다.
프로세스 제어 블록 (PCB)
운영체제는 수많은 프로세스를 관리하기 위해 각 프로세스의 모든 정보를 기록해두는 특별한 데이터 구조를 사용한다. 이것이 바로 **프로세스 제어 블록(Process Control Block, PCB)**이다. PCB는 프로세스의 ‘주민등록증’ 또는 병원의 ‘환자 차트’와 같다.
PCB에는 다음과 같은 핵심 정보들이 저장된다.
- 
프로세스 식별자 (PID, Process ID): 각 프로세스를 고유하게 식별하는 번호.
 - 
프로세스 상태 (Process State): 현재 프로세스가 어떤 상태에 있는지 (생성, 준비, 실행, 대기, 종료 등).
 - 
프로그램 카운터 (Program Counter, PC): 이 프로세스가 다음에 실행할 명령어의 주소.
 - 
CPU 레지스터: 이 프로세스가 직전에 사용하던 CPU 레지스터 값들의 백업. (Accumulator, Index Registers 등)
 - 
CPU 스케줄링 정보: 프로세스의 우선순위, 스케줄링 큐에 대한 포인터 등.
 - 
메모리 관리 정보: 해당 프로세스가 할당받은 메모리 공간의 정보 (e.g., 페이지 테이블, 세그먼트 테이블).
 - 
입출력 상태 정보: 프로세스에 할당된 입출력 장치, 열린 파일 목록 등.
 
운영체제는 이 PCB들을 관리하며 전체 시스템의 프로세스들을 제어한다. 예를 들어, 어떤 프로세스를 잠시 중단시키고 다른 프로세스를 실행시켜야 할 때, 운영체제는 현재 실행 중인 프로세스의 모든 상태를 PCB에 저장하고, 새로 실행할 프로세스의 PCB에서 상태를 읽어와 복원한다. 이 과정을 통해 프로세스 간의 전환이 매끄럽게 이루어진다.
3장 프로세스의 일생 생성부터 소멸까지
프로세스는 프로그램이 실행되면서 생성되고, 여러 상태를 거치다가 최종적으로 종료된다. 이 과정을 ‘프로세스 생명 주기(Process Life Cycle)‘라고 부르며, 일반적으로 5가지 상태로 구분한다.
- 
생성 (New):
- 
사용자가 프로그램을 실행하거나 시스템이 필요에 의해 프로세스를 만들 때의 초기 상태.
 - 
운영체제는 이 단계에서 프로세스를 위한 PCB를 생성하고 메모리를 할당하는 등의 준비 작업을 수행한다.
 
 - 
 - 
준비 (Ready):
- 
프로세스가 생성되고 CPU를 할당받기 위해 기다리는 상태.
 - 
메모리 할당 등 실행에 필요한 모든 준비는 마쳤지만, 아직 자신의 차례가 오지 않아 CPU 스케줄러의 선택을 기다리고 있다.
 - 
준비 상태의 프로세스들은 **준비 큐(Ready Queue)**에서 대기한다.
 
 - 
 - 
실행 (Running):
- 
프로세스가 CPU를 할당받아 명령어들을 실제로 수행하는 상태.
 - 
한 시스템에 CPU 코어가 하나라면, 특정 시점에는 오직 하나의 프로세스만이 실행 상태에 있을 수 있다.
 
 - 
 - 
대기 (Waiting / Blocked):
- 
실행 중이던 프로세스가 입출력(I/O) 작업이나 특정 이벤트(e.g., 파일 읽기, 데이터 수신)를 기다려야 할 때 들어가는 상태.
 - 
예를 들어, 하드 디스크에서 대용량 파일을 읽어야 할 때, CPU는 그냥 기다리는 것이 아니라 이 프로세스를 대기 상태로 보내고 다른 준비 상태의 프로세스를 실행시켜 효율을 높인다.
 - 
원인이 된 이벤트가 완료되면, 프로세스는 다시 준비(Ready) 상태로 돌아가 CPU 할당을 기다린다.
 
 - 
 - 
종료 (Terminated):
- 
프로세스가 실행을 모두 마치고 종료된 상태.
 - 
운영체제는 이 프로세스가 사용하던 모든 자원(메모리, 파일 등)을 회수하고 PCB를 폐기한다.
 
 - 
 
이러한 상태 전이는 운영체제의 **스케줄러(Scheduler)**에 의해 능동적으로 관리되며, 시스템의 자원을 가장 효율적으로 사용하도록 설계되었다.
4장 CPU의 저글링 쇼 스케줄링과 컨텍스트 스위칭
멀티태스킹은 CPU가 마법처럼 여러 일을 동시에 처리하는 것이 아니다. 실제로는 매우 짧은 시간 동안 여러 프로세스 사이를 빠르게 오가며 조금씩 실행하는 ‘저글링’에 가깝다. 이 저글링을 지휘하는 것이 바로 CPU 스케줄러와 컨텍스트 스위칭이다.
CPU 스케줄링
CPU 스케줄러는 준비 큐에 있는 여러 프로세스 중에서 어떤 프로세스에게 CPU를 할당할지 결정하는 운영체제의 핵심 구성 요소다. 스케줄러의 목표는 CPU 활용률, 처리량(Throughput)은 극대화하고, 응답 시간(Response Time), 대기 시간(Waiting Time)은 최소화하는 것이다.
스케줄러는 작동 시점에 따라 크게 세 종류로 나눌 수 있다.
- 
장기 스케줄러 (Long-term Scheduler / Job Scheduler):
- 
어떤 프로세스를 메모리에 적재하여 준비 큐에 넣을지 결정한다.
 - 
시스템의 전체 프로세스 수를 조절하여 멀티프로그래밍의 정도(Degree of Multiprogramming)를 제어한다.
 
 - 
 - 
단기 스케줄러 (Short-term Scheduler / CPU Scheduler):
- 
준비 큐에 있는 프로세스 중 어떤 프로세스에게 CPU를 할당할지 결정한다.
 - 
밀리초(ms) 단위로 매우 빈번하게 호출되므로 속도가 매우 빨라야 한다.
 
 - 
 - 
중기 스케줄러 (Medium-term Scheduler):
- 
메모리 부족 등의 이유로 일부 프로세스를 메모리에서 잠시 디스크로 내보내는 **스와핑(Swapping)**을 수행한다.
 - 
이를 통해 시스템의 부하를 조절하고 메모리 공간을 확보한다.
 
 - 
 
컨텍스트 스위칭 (Context Switching)
컨텍스트 스위칭은 하나의 프로세스에서 다른 프로세스로 CPU 제어권을 넘겨주는 과정을 의미한다. 이는 다음과 같은 순서로 진행된다.
- 
인터럽트(Interrupt) 또는 시스템 호출(System Call) 발생: 실행 중인 프로세스 A의 타임 슬라이스가 만료되거나, 입출력 요청이 발생한다.
 - 
현재 프로세스(A) 상태 저장: 운영체제는 프로세스 A의 현재 실행 상태(Program Counter, 레지스터 값 등)를 프로세스 A의 PCB에 저장한다.
 - 
다음 프로세스(B) 선택: CPU 스케줄러가 준비 큐에서 다음에 실행할 프로세스 B를 선택한다.
 - 
다음 프로세스(B) 상태 복원: 운영체제는 프로세스 B의 PCB에 저장된 상태를 읽어와 CPU 레지스터 등에 복원시킨다.
 - 
실행 재개: 복원된 상태로부터 프로세스 B의 실행을 시작한다.
 
이 과정은 마치 한 요리사가 파스타를 만들다가 잠시 멈추고, 현재까지의 조리 상태(끓는 물의 온도, 소스의 농도 등)를 메모해둔 뒤, 케이크 반죽을 하러 가는 것과 같다. 다시 파스타를 만들러 돌아왔을 때는 메모해둔 상태를 보고 정확히 그 지점부터 다시 시작할 수 있다.
컨텍스트 스위칭은 멀티태스킹의 핵심이지만, 상태를 저장하고 복원하는 데 시간이 소요되므로 **오버헤드(Overhead)**가 발생한다. 따라서 너무 잦은 컨텍스트 스위칭은 오히려 시스템 성능을 저하시킬 수 있다.
5장 프로세스 간의 협업 IPC (Inter-Process Communication)
각 프로세스는 독립된 메모리 공간을 갖지만, 때로는 서로 데이터를 주고받거나 작업 진행 상황을 알려주며 협력해야 할 필요가 있다. 이처럼 프로세스들 간에 데이터를 교환하는 메커니즘을 **프로세스 간 통신(IPC, Inter-Process Communication)**이라고 한다.
IPC는 운영체제가 제공하는 기능을 통해 이루어지며, 대표적인 방법은 다음과 같다.
- 
파이프 (Pipe):
- 
하나의 프로세스가 출력을 보내면 다른 프로세스가 입력을 받는 단방향 통신 채널.
 - 
두 프로세스가 부모-자식 관계일 때 주로 사용되며 구현이 간단하다.
 - 
예:
ls -l | grep "test"와 같은 쉘 명령어에서|가 파이프 역할을 한다. 
 - 
 - 
공유 메모리 (Shared Memory):
- 
여러 프로세스가 공유하는 메모리 공간을 생성하여 통신하는 방식.
 - 
데이터를 직접 메모리에 쓰고 읽기 때문에 IPC 방식 중 가장 속도가 빠르다.
 - 
하지만 여러 프로세스가 동시에 접근할 경우 데이터 일관성 문제가 발생할 수 있으므로, **세마포어(Semaphore)**나 뮤텍스(Mutex) 같은 동기화 기법이 반드시 필요하다.
 
 - 
 - 
메시지 큐 (Message Queue):
- 
메시지를 담는 큐(Queue) 형태의 자료구조를 커널 공간에 생성하여 통신하는 방식.
 - 
보내는 측은 메시지를 큐에 넣고, 받는 측은 큐에서 메시지를 꺼내 간다.
 - 
비동기적으로 데이터를 주고받을 수 있다는 장점이 있다.
 
 - 
 
6장 심화 과정 프로세스와 스레드의 차이
현대 운영체제에서는 프로세스보다 더 작은 실행 단위인 **스레드(Thread)**라는 개념이 널리 사용된다. 스레드는 ‘경량 프로세스(Lightweight Process)‘라고도 불린다.
프로세스와 스레드의 가장 결정적인 차이는 ‘자원 공유’에 있다.
- 
프로세스: 각 프로세스는 자신만의 코드, 데이터, 힙 영역을 독립적으로 가진다. 스택 영역 또한 독립적이다. 자원을 공유하지 않는 것이 원칙이다.
 - 
스레드: 하나의 프로세스 내에 여러 스레드가 존재할 수 있다. 이 스레드들은 부모 프로세스의 코드, 데이터, 힙 영역을 공유한다. 하지만 각 스레드는 자신만의 독립적인 스택과 레지스터를 가진다.
 
이러한 구조적 차이 때문에 다음과 같은 특징이 나타난다.
| 구분 | 프로세스 (Process) | 스레드 (Thread) | 
|---|---|---|
| 메모리 구조 | 독립적인 메모리 공간 (Code, Data, Heap, Stack) | Code, Data, Heap 공유, 독립적인 Stack | 
| 자원 공유 | IPC를 통해서만 가능 (복잡하고 느림) | 메모리 공유로 인해 직접 통신 가능 (간단하고 빠름) | 
| 생성/컨텍스트 스위칭 | 무겁고 느림 (많은 자원 할당 및 상태 저장 필요) | 가볍고 빠름 (공유 자원이 많아 최소한의 상태만 저장) | 
| 안정성 | 한 프로세스의 오류가 다른 프로세스에 영향을 주지 않음 | 한 스레드의 오류가 전체 프로세스를 다운시킬 수 있음 | 
웹 브라우저를 예로 들면, 브라우저 자체는 하나의 프로세스다. 그리고 그 안에서 화면을 그리는 스레드, 네트워크 통신을 하는 스레드, 사용자 입력을 처리하는 스레드 등이 동시에 실행되면서 빠르고 부드러운 사용자 경험을 제공하는 것이다.
결론 보이지 않는 영웅, 프로세스
지금 이 순간에도 당신의 컴퓨터 운영체제는 수십, 수백 개의 프로세스를 끊임없이 관리하고 있다. 프로세스는 운영체제가 컴퓨터의 제한된 자원을 효율적으로 분배하고, 여러 작업을 동시에 처리하는 것처럼 보이게 만드는 핵심적인 추상화 개념이다. 프로세스의 탄생과 구조, 생명 주기, 그리고 스케줄링 방식을 이해하는 것은 컴퓨터 시스템의 동작 원리를 꿰뚫어 보는 것과 같다. 눈에 보이지는 않지만, 우리의 모든 디지털 경험을 가능하게 하는 이 ‘보이지 않는 영웅’의 역할은 아무리 강조해도 지나치지 않다.