개발 일기

[OS] 프로세스(Process)와 스레드(Thread) 본문

Computer Science/Operating System

[OS] 프로세스(Process)와 스레드(Thread)

개발 일기장 주인 2025. 3. 21. 16:35
프로세스 : 메모리상에서 실행 중인 프로그램
스레드 : 프로세스가 할당받은 리소스를 가지고 실제로 실행되는 작업의 단위 (Execution of Unit)

시작하기에 앞서 우리가 흔히 프로그램과 프로세스라는 단어를 많이 쓰는데 이 둘을 확실하게 구분하고 갈 필요가 있을 것 같다.

💡 프로그램(Program)과 프로세스(Process)의 차이

정의 실행 가능한 정적인 코드 실행 중인 동적인 개체
저장 위치 디스크(SSD, HDD)에 저장됨 메모리(RAM)에서 실행됨
상태 실행되지 않음 (정적인 상태) 실행 중 (동적인 상태)
생명주기 실행되지 않으면 계속 존재 실행이 끝나면 사라짐
예제 Safari.app, IntelliJ IDEA.app, chrome.exe chrome.exe가 실행 중인 상태

EX) IntelliJ IDEA

(좌) Executable 파일 형태로 존재하는 상태 - 실행X / (우) 실행시켜 CPU, 메모리 등 리소스를 할당받고 프로세스가 된 상태 - 실행O

 

→ 즉, 소스코드 또는 실행 파일을 실행시키면, 해당 프로그램은 RAM에 로드되고 리소스를 할당받아 프로세스가 된다.


✅ 프로세스(Process)

  • 메모리에 로드되어 실행 중인 프로그램의 인스턴스
    → 이때  프로그램을 통째로 직접 올리는 것이 아니라 OS가 프로세스에 할당한 Virtual Memory를 활용하여 필요한 부분만 물리 메모리(RAM)로 로드하고, 나머지는 디스크에 저장하여 필요할 때 불러오는 방식으로 동작한다.
  • 즉, 실행 중인 프로그램 = 프로세스
  • 운영체제는 각 프로세스의 실행 상태, 메모리 정보, CPU 스케줄링 정보를 저장하는 PCB(Process Control Block)를 관리

  • 이렇게 4가지가 메모리 영역에 할당되고 이와 함께, 운영체제는 PCB (Process Control Block)를 생성하여 프로세스를 관리한다.

Process 상태 전의

더보기

Process 상태 전의

 

  1. Admitted (new → ready) : 프로세스 생성을 승인 받음
  2. Dispatch (ready→ running) : 준비 상태에 있는 여러 프로세스들 중 하나가 스케줄러에 의해 실행됨
  3. Interrupt (running → ready) : Timeout, 예기치 않은 이벤트가 발생하여 현재 실행 중인 프로세스를 준비 상태로 전환하고, 해당 작업을 먼저 처리
  4. I/O or event wait (running → wainting) : 실행 중인 프로세스가 입출력이나 이벤트를 처리해야 하는 경우, 입출력이나 이벤트가 끝날 때까지 대기 상태로 전환
  5. I/O or event completion (waiting → ready) : 입출력이나 이벤트가 모두 끝난 프로세스를 다시 준비 상태로 만들어 스케줄러에 의해 선택될 수 있는 상태로 전이

 

 1️⃣ 단일 프로세스(Single-Process)과 그 한계

단일 프로세스 시스템에서는 CPU 사용률이 비효율적일 수 있다.

 

예를 들어 위와 같이 하나의 프로세스 P1만 실행되는 경우, P1이 실행되다가 I/O 작업을 수행하는 동안 "CPU는 유휴 상태"가 된다.

이는 단일 프로세스 시스템의 주요 단점이다.

이를 해결하기 위해 여러 개의 프로그램을 메모리에 올려 동시에 실행하는 방식이 도입되었다.

즉, P1이 I/O 작업을 수행하는 동안, P2와 같은 다른 프로세스가 CPU를 점유하여 작업을 수행할 수 있도록 하는 것이다.


2️⃣ 멀티 프로그래밍(Multi-Programming)과 그 한계

멀티 프로그래밍은 여러 개의 프로그램을 메모리에 적재하고, CPU가 한 프로세스의 I/O 작업을 기다리는 동안 다른 프로세스를 실행하도록 한다. 이를 통해 CPU의 유휴 시간을 최소화하고 시스템 자원을 더욱 효율적으로 활용할 수 있다.

 

예를 들어, P1이 실행 중에 디스크 I/O 요청을 보내면, CPU는 P1의 작업이 끝날 때까지 유휴 상태로 대기하는 대신, 다른 프로세스 P2를 실행하여 CPU를 활용한다. P2가 리소스를 선점하는 동안 P1은 I/O 작업을 마친 후 준비 상태로 돌아가고, 이후 CPU가 비면 P1이 다시 실행됩니다.

 

즉, 멀티 프로그래밍은 "CPU 활용률을 극대화하는 데 초점" 맞춘 개념이다.

이 과정에서 PCB에 대해 이해를 한다면 어떻게 Context Switching이 돌아가는지 더 이해하기 쉬울 것이다.

 

PCB & Context Switching

더보기

PCB & Context Switching


PCB (Process Control Block)

프로세스가 생성될 때마다 운영체제는 그 프로세스에 대응하는 PCB를 Process Table을 통해운영체제의 커널 영역에 생성

운영체제에 따라 PCB에 포함되는 항목이 다를 수 있지만 일반적으로 PCB내 에는 다음과 같은 정보가 포함되어 있다.

  • 포인터 (Pointer) : 프로세스의 현재 위치를 저장하는 포인터 정보
  • 프로세스 상태 (Process state) : 프로세스의 각 상태 - 생성(New), 준비(Ready), 실행(Running), 대기(Waiting), 종료(Terminated) 를 저장
  • 프로세스 아이디 (Process ID, PID) : 프로세스 식별자를 지정하는 고유한 ID
  • 프로그램 카운터 (Program counter) :  프로세스를 위해 실행될 다음 명령어의 주소를 포함하는 카운터를 저장
  • 레지스터 (Register) : 누산기, 베이스, 레지스터 및 범용 레지스터를 포함하는 CPU 레지스터에 있는 정보
  • 메모리 제한 (Memory Limits) : 운영 체제에서 사용하는 메모리 관리 시스템에 대한 정보
  • 열린 파일 목록 (List of open file) : 프로세스를 위해 열린 파일 목록

Context Switching 과정

두 개의 프로세스 간에 컨텍스트 스위칭 과정을 그림으로 표현한 것이다.

  1. CPU는 Process P1을 실행한다 (Executing)
  2. 일정 시간이 지나 Interrupt 또는 system call이 발생한다. (CPU는 idle 상태)
  3. 현재 실행 중인 Process P1의 상태를 PCB1에 저장한다. (Save state into PCB1)
  4. 다음으로 실행할 Process P2를 선택한다. (CPU 스케줄링)
  5. Process P2의 상태를 PCB2에서 불러온다. (Reload state from PCB2)
  6. CPU는 Process P2를 실행한다. (Executing)
  7. 일정 시간이 지나  Interrupt 또는 system call이 발생한다. (CPU는 idle 상태)
  8. 현재 실행 중인 Process P2의 상태를 PCB2에 저장한다. (Save state into PCB2)
  9. 다시 Process P1을 실행할 차례가 된다. (CPU 스케줄링)
  10. Process P1의 상태를 PCB1에서 불러온다. (Reload state from PCB1)
  11. CPU는 Process P1을 중간 시점 부터 실행한다. (Executing)

‼️ 한계 ‼️

그러나 단점은 적절한 스케줄링이 이루어지지 않으면, P2가 계속해서 CPU를 점유하게 되고, P2는 계속 대기 상태에 놓이게 된다는 점이다.


3️⃣ 멀티태스킹(Multi-Tasking)과 그 한계

멀티 프로그래밍이 CPU 활용률을 극대화하는 개념이라면, 멀티태스킹은 여러 프로세스가 동시에 실행되는 것처럼 보이게 하며, 운영체제가 CPU 시간을 여러 프로세스에 나누어 주는 방식이다.
동시 처리(concurrent processing)

Concurrent vs Parallel (동시성과 병렬성 차이)

멀티 프로그래밍 방식에서는 하나의 프로세스가 CPU를 차지하는 동안 다른 프로세스는 대기해야 하지만, 멀티태스킹에서는 CPU가 빠르게 여러 프로세스를 전환(Context Switching)하면서 동시에 실행되는 것처럼 보이게 한다.

 

즉, 운영체제는 시분할 방식(Time Sharing)을 통해 여러 프로세스가 번갈아 가며 실행되도록 조정한다.

 

‼️ 한계 ‼️

  • 병렬 처리 X
    멀티태스킹은 여러 프로세스를 동시에 실행하는 것처럼 보이게 하지만, 하나의 프로세스가 동시에 여러 작업을 수행하는 것은 아니다. 

  • 컨텍스트 스위칭 시 발생하는 비용
    프로세스 간의 전환 시, 현재 실행 중인 프로세스의 상태를 PCB에 저장하고, 새로운 프로세스의 상태를 PCB로 부터 복원하는데 시간이 걸린다.
    이 과정에서 프로그램 카운터, 레지스터 값, 메모리 정보 등 프로세스의 상태를 교체해야 하므로 오버헤드가 발생한다.
    + CPU 캐시 메모리 무효화에 따른 비용, 프로세스 스케줄링 비용

  • 프로세스 간 데이터 공유의 어려움
    여러 프로세스가 각각 독립된 메모리 공간을 가지고 있기 때문에, 프로세스 간 통신(IPC)이 필요하다.
    데이터 공유가 복잡하고 속도가 느리기 때문에 효율적인 데이터 공유가 어려울 수 있다.

이라한 한계들을 극복하기 위해 스레드가 도입된다.


✅ 해결책: 경량화된 실행 단위 스레드(Thread)

  • 하나의 프로세스 내부에서 실행되는 작은 실행 단위로, CPU에서 실제로 실행되는 작업의 단위이다. (Unit of Execution)
  • Process는 최소 1개의 Thread 존재
  • 같은 프로세스의 자원을 공유
  • Code, Data, Heap 영역은 공유하고, Stack & Thread Local Storage(TLS)만 개별적으로 할당되기 때문에 컨텍스트 스위칭 시 교체해야 할 정보가 줄 어들어 오버헤드가 감소
     쉽게 말해 모조리 다 빼고 모조리 다시 넣을 필요가 없다.
  • 모든 Thread는 해당 Process에게 할당된 가상 메모리와 시스템 리소스 내에서만 실행

같은 프로세스 내 Thread는 메모리 영역을 공유 (Stack만 분리됨)

 


⁉️ 스레드의 장점

  1. 프로세스보다 컨텍스트 스위칭 비용이 적음 (Stack 정보만 교체)
  2. 메모리 사용량이 줄어듦 (새로운 프로세스를 생성하지 않고 기존 자원을 공유)
  3. 데이터 공유가 쉬움 (IPC 없이 같은 Heap, Data 영역 사용)

 

‼️ 스레드의 한계 ‼️

  1. 동기화 문제 발생 가능 (여러 스레드가 같은 자원을 접근할 때 충돌 가능)
  2. 하나의 스레드가 비정상 종료되면 전체 프로세스가 영향을 받을 수 있음(Internet Explorer)

이제 하나의 프로그램을 처리하기 위한 멀티 프로세스(Multi-process)와 멀티 스레드(Multi-thread) 방식에 대해 비교하자.

이때 Multi-Process라고 해서 여러 개의 어플리케이션이 실행되는 것이 아니라 하나의 어플리케이션을 동작시킬때 두 가지 처리 방식을 비교한다고 생각해야한다.

 

Multi-Process vs Multi-Thread: "하나의 프로그램 내에서의 처리 방식" 비교

🔸 Multi-Process

멀티 프로세스 방식은 하나의 프로그램이 여러 개의 독립적인 프로세스를 생성하여 동시에 작업을 처리하는 방식이다.

각 프로세스는 독립된 메모리 공간과 리소스를 가지며, 프로세스 간에 직접적인 데이터 공유는 불가능하고 IPC를 통해 가능하다.(통신비용)

그러나 동기화 작업이 필요없고 여러 개의 프로세스가 각기 다른 CPU 코어에서 실행되면 병렬 처리(parallelism)가 가능

ex) 로그인 요청 

  • 예를 들어, 여러 사용자가 동시에 로그인 요청을 할 경우, 부모 프로세스는 fork()를 통해 자식 프로세스를 생성한다.
  • 각 자식 프로세스는 독립적인 메모리 공간을 가지며, 각자의 로그인 요청을 처리한다.

장점

  • 독립성
    이러한 방식은 각 프로세스가 독립적이기 때문에 하나의 프로세스가 문제가 발생하더라도 다른 프로세스에는 영향을 미치지 않는다.
    ex)  예를 들어, Chrome은 멀티 프로세스 방식을 사용하여 각 탭이 독립적인 프로세스로 실행된다. 이로 인해 하나의 탭에서 문제가 발생하더라도, 다른 탭에는 영향을 주지 않는다.

단점

  • 메모리 사용
    각 프로세스가 독립적인 메모리 공간을 가지기 때문에, 메모리 소모가 크고, 메모리 관리가 복잡하다.

  • 통신 비용
    프로세스 간 데이터 공유는 IPC를 통해서만 가능하며, 이때 발생하는 통신 비용이 성능을 저하시킬 수 있다.

  • Context Switching 비용
    프로세스 간 전환 (context switching) 시, 운영 체제는 각각의 프로세스 상태를 저장하고 복구해야 하므로 비용이 발생합니다.

🔸 Multi-Thread

반면에 멀티 스레드는 하나의 프로그램(프로세스) 내에서 여러 실행 흐름(스레드)을 동시에 실행하는 방식이다. 
하나의 프로세스 내에서 여러 스레드를 생성하여 각각 로그인 요청을 동시에 처리하게 된다.

모든 스레드는 같은 메모리 공간과 자원을 공유하므로, 스레드 간에 데이터를 직접 공유할 수 있다.

 

장점

  • Context Switching 비용 
    스레드 간 전환은 동일한 메모리 공간을 공유하므로 상대적으로 적은 비용이 들고, CPU 레지스터 상태만 저장하고 복구하면 되기 때문에 더 효율적

단점

  • 동기화 문제 (Race Condition)
    • 스레드는 같은 메모리 공간을 공유하기 때문에, 여러 스레드가 동시에 동일한 데이터를 수정하려고 할 때 경쟁 상태(Race Condition)가 발생할 수도 있다.
    • 이러한 경쟁 상태를 방지하기 위해서는 동기화(Synchronization)가 필요합니다. 이를 위해 mutexes, semaphores, locks 등을 사용하여 스레드 간의 동시 접근을 제어한다.
       
  • 메모리 영역 공유로 인한 장애 전파
    • 스레드들은 프로세스 내에서 메모리 공간을 공유하므로, 하나의 스레드에서 문제가 발생하거나 예외가 발생할 경우 다른 스레드에도 영향을 미칠 수 있다.
    • 한 스레드가 메모리 접근 오류를 일으키면 그 오류가 다른 스레드에게도 전파되어 전체 프로세스가 종료되거나 불안정해질 수 있다.

비교

싱글 코어 or 싱글 프로세서 환경에서의 멀티 프로세스와 멀티 스레드를 비교해보자.

 

멀티 프로세스는 여러 개의 독립적인 프로세스를 생성하고, 각 프로세스는 독립된 메모리 공간을 할당받는다.

싱글 코어에서 실행되는 멀티 프로세스는 실제로 한 번에 하나의 프로세스만 실행될 수 있으며, CPU는 시간 분할 방식을 사용해 각 프로세스가 순차적으로 실행되도록 한다.

이때, 프로세스 간의 Context Switching은 상대적으로 느리며, 각각의 프로세스는 독립적이기 때문에 안정성을 가져갈 수 있는 장점이 있지만, 자원을 공유하지 않기 때문에 효율성은 떨어질 수 있다.

반면, 멀티 스레드는 하나의 프로세스 내에서 여러 스레드가 메모리 공간을 공유하며 실행된다.

싱글 코어에서는 마찬가지로 시간 분할 방식으로 스레드들이 실행되지만, 스레드 간의 Context Switching 프로세스보다 빠르며, 자원을 공유하기 때문에 효율적인 데이터 처리와 빠른 작업 전환이 가능하다.

하지만 스레드들 간에 자원을 공유하기 때문에 하나의 스레드에서 발생한 오류나 예외가 다른 스레드에 영향을 미칠 수 있다. 그렇기 때문에 효율적이겠지만 안정성은 멀티 프로세스에 비해 떨어진다.