Process vs Thread

smc2315·2024년 3월 27일

OS

목록 보기
1/2

1. Process

  • 프로세스(process)란 실행중에 있는 프로그램(Program)을 의미한다.
  • 스케줄링의 대상이 되는 작업(task)과 같은 의미로 쓰인다.
  • 프로그램은 일반적으로 하드 디스크 등에 저장되어 있는 실행코드를 뜻하고, 프로세스는 프로그램을 구동하여 프로그램 자체와 프로그램의 상태가 메모리 상에서 실행되는 작업 단위를 지칭한다.

1-1. Process의 메모리 구조

  • 프로세스를 실행시키기 위해서는 코드의 데이터를 메모리에 올려 실행시켜야 한다.
  • 프로세스마다 고유한 가상 메모리 공간을 제공하며, 이 공간은 4개로 나눌 수 있다.

1. code 영역(Text Segment)

  • 내가 작성한 코드가 저장되는 공간으로, 코드는 컴파일 되어 0과 1로 변환된 기계어가 저장된다.

2. Data 영역(Data Segment)

  • 내가 작성한 코드에서 선언된 전역 변수, 정적 변수, 상수 등을 저장한다.
  • 데이터 영역은 프로그램의 시작 시 초기화되며, 프로그램이 종료될 때까지 유지된다.
  • 초기화된 변수와 초기화되지 않은 변수들이 나눠서 저장된다.

BSS(Block Stated Symbol) 영역

  • 초기화 되지 않은 전역변수가 저장되는 영역
  • 초기화 된 전역변수는 Data 영역에 저장되어 비휘발성 메모리인 ROM에 저장되는데 이 부분은 비용이 많이 들어 RAM에 저장될 것과 ROM에 저장될 것을 구분하기 위해 영역을 구분해 사용한다.

3. Stack

  • 지역변수, 매개변수, 리턴값 등 잠시 사용되었다가 사라지는 데이터를 저장하는 영역
  • 프로세스마다 독립적인 stack을 가질 수 있고, stack 포인터를 통해 스택의 상태를 관리한다.
  • 함수가 호출되면 stack 공간이 생성되며, 함수가 종료되면 제거된다.

4. Heap

  • 동적으로 생성되는 데이터 구조나 객체들을 저장한다.
  • 프로그램 동작 시(런타임)에 크기가 결정된다.
  • 커널 영역을 보호하기 위해 메모리의 낮은 주소에서 높은 주소의 방향으로 메모리가 할당된다.
  • Stack 영역은 높은 주소 공간에서 낮은 주소 공간으로 데이터가 저장되고 Heap 영역은 반대로 낮은 주소 공간에서 높은 주소 공간으로 데이터가 저장되는데, 이러한 구조를 가지게 된 이유는 데이터를 아무리 입력해도 Kernel 영역 반대로 데이터가 저장되어 Kernel 영역을 침범할 수 없기 때문이다.

1-2. 프로세스의 자원 공유

  • 기본적으로 각 프로세스는 메모리에 별도의 주소 공간에서 실행되기 때문에, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수는 없다.
  • 하지만 IPC를 활용하여 프로세스 간 정보를 공유할 수 있다.

프로세스 통신 방법의 종류

1. 운영체제에서 지원하는 방식

  • 공유 메모리
  • 메모리 맵
  • 메시지 패싱: 파이프
  • 커널 메시지 큐
  • 파일
  • 등등..
  1. 네트워크를 사용하는 방식
  • 소켓, Http 등
  • 네트워크 메시지 큐
  • RPC
  • DBMS, 캐시
  • 등등..

1-3. 프로세스 스케쥴링

  • 프로세스 스케줄링(Process Scheduling)은 운영체제에서 CPU를 사용할 수 있는 프로세스를 선택하고, CPU를 할당하는 작업을 말한다.
  • 프로세스 스케줄링은 프로세스의 우선순위, 작업량 등을 고려하여 효율적으로 배치하여, 이를 통해 운영체제는 CPU를 효율적으로 사용하며 시스템 전반적인 성능을 향상시킨다.
  • 대표적으로 FCFS, SJF, Priority, RR 등의 알고리즘이 있다.

1-4. 프로세스의 상태

  • 프로세스의 상태는 프로세스가 실행되는 동안 변경되는 고유 상태를 의미한다.
  • 프로세스가 생성되어 실행하기 까지 프로세스는 여러가지의 상태를 갖게 되고, 상태의 변화에 따라 프로세스가 동작되는 것이다.
  • 프로세스는 일반적으로 다음과 같은 5가지 상태를 가진다.

1. 프로세스 생성(new)

  • 프로세스가 생성된 상태
  • 생성만 되었고, 아직 실행되기 위한 자원을 할당받지 못한 상태

2. 실행 가능(Ready)

  • 프로세스가 실행을 기다리는 상태
  • 프로세스가 필요한 자원을 모두 할당받았으며, 실행을 위한 준비가 완료되었지만 CPU를 할당받지 못한 상태
  • 이 상태에서는 CPU를 할당받기 위해 스케줄링 대기열(Queue)에 들어가게 된다.

3. 실행 상태(Running)

  • 프로세스가 CPU를 할당받아 실제로 코드를 실행하는 상태
  • 이 상태에서는 프로세스가 작업을 처리하고 결과를 만들어 낸다.

4. 대기(Blocked)

  • 프로세스를 처리중에 작업 시간이 초과되거나 자원 사용을 위해 대기해야 하는 이벤트가 발생해서 프로세스가 잠시 멈춘 상태
  • 이 상태에서는 CPU를 사용하지 않는다.
  • 특정 자원을 사용할 수 있을 때까지 실행을 멈추고, 다시 대기열(Ready Queue)로 들어가게 되며, 프로세스 처리 가능 상태가 되면 실행(Running) 상태로 변경한다.

5. 종료(Terminated, exit)

  • 프로세스의 실행이 완료되어 종료된 상태
  • 이 상태에서는 할당된 자원이 해제되고, 프로세스의 메모리 공간은 운영체제에 반환된다.

1-5. 프로세스 상태전이

  • 프로세스 상태 전이란 프로세스가 실행되는 동안 상태가 OS에 의해 변경되는 것을 말한다.
  • 운영체제는 프로세스의 상태를 감시하고, 프로세스 상태를 기반으로 프로세스 스케쥴링을 통해 프로세스를 관리하고 제어한다.
  • Admitted (new → ready) : 프로세스 생성을 승인 받음
  • Dispatch (ready→ running) : 준비 상태에 있는 여러 프로세스들 중 하나가 스케줄러에 의해 실행됨
  • Interrupt (running → ready) : Timeout, 예기치 않은 이벤트가 발생하여 현재 실행 중인 프로세스를 준비 상태로 전환하고, 해당 작업을 먼저 처리
  • I/O or event wait (running → wainting) : 실행 중인 프로세스가 입출력이나 이벤트를 처리해야 하는 경우, 입출력이나 이벤트가 끝날 때까지 대기 상태로 전환
  • I/O or event completion (waiting → ready) : 입출력이나 이벤트가 모두 끝난 프로세스를 다시 준비 상태로 만들어 스케줄러에 의해 선택될 수 있는 상태로 전환

1-6. PCB(Process Control Block)

  • 운영체제가 프로세스를 제어하기 위해 정보를 저장해 놓는 곳으로, 프로세스의 상태 정보를 저장하는 구조체
  • 프로세스의 상태 관리와 문맥 교환(Context Switching)을 위해서 필요하다.
  • 프로세스가 생성될 때마다 고유의 PCB 가 생성되며, 프로세스가 완료되면 PCB는 제거된다.
  • Pointer : 프로세스의 현재 위치를 저장하는 포인터 정보
  • Process Number(Process ID) : 프로세스 식별자를 지정하는 고유한 ID
  • Process State : 프로세스의 상태 (Create, Ready, Running 등등)
  • Program Counter : 프로세스를 위해 실행될 다음 명령어의 주소
  • Register : Accumulator, General Register 등을 포함하는 CPU Register의 값
  • Memory Limits : 운영 체제에서 사용하는 메모리 관리 시스템에 대한 정보
  • List of open file : 프로세스를 위해 열린 파일 목록

1-7. Context Switching

  • CPU가 한 프로세스에서 다른 프로세스로 전환할 때 발생하는 일련의 과정
  • CPU는 한 번에 하나의 프로세스만 실행할 수 있으므로, 여러 개의 프로세스를 번갈아가며 실행하여 CPU 활용률을 높이기 위해 컨텍스트 스위칭이 필요하다.
  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)

Context Switching Overhead

컨텍스트 스위칭을 할 때 다음과 같은 오버헤드가 발생한다.

  • PCB 저장 및 복원 비용
  • CPU 캐시 메모리 무효화에 따른 비용
  • 프로세스 스케줄링 비용

컨텍스트 스위칭 과정은 사용자로금 빠른 반응성과 동시성을 제공하지만, 실행되는 프로세스의 변경 과정에서 프로세스의 상태, 레지스터 값 등이 저장되고 불러오는 등의 작업이 수행하기 때문에 시스템에 많은 부담을 주게된다.

2. Thread

  • 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미
  • 모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
  • 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.
  • 스레드는 프로세스 내에서 각각 Stack만 따로 할당받고 Code, Data, Heap 영역은 공유한다.

2-1. Thread의 유형

1. 커널 수준 스레드(1 : 1 매핑 방식)

  • 스레드를 OS(커널)이 직접 관리(스레드 생성, 스케줄링 등등)
  • 커널이 전체 TCB와 PCB를 관리한다.

장점

  • 커널이 각 스레드를 개별적으로 관리
  • 프로세스 내 스레드들이 병행 수행 가능
  • 하나의 스레드가 block 되어도 다른 스레드는 계속 작업 가능

단점

  • 커널 영역에서 스레드의 생성 및 관리
  • 문맥 교환으로 인한 오버헤드가 큼
  • 사용자 스레드보다 생성 및 관리 속도가 느림

2. 사용자 구준 스레드(N : 1 매핑 방식)

  • 사용자 영역의 스레드 라이브러리로 구현하며, 라이브러리는 스레드의 생성, 스케줄링 담당한다.
  • 커널은 스레드의 존재를 인식하지 못하기 때문에 커널의 개입을 받지 않는다.
  • 스레드 정보(TCB, Thead Control Block)는 프로세스 내에서, 프로세스 정보(PCB, Process Control Block)는 커널에서 관리한다.

장점

  • 커널의 개입을 받지 않아 스레드의 생성 및 관리의 부하가 적음
  • 동일한 메모리 영역에서 스레드가 생성 및 관리되므로 속도가 빠름
  • 라이브러리를 통한 이식성이 높음

단점

  • 커널은 프로세스 단위로 자원을 할당하기 때문에 하나의 스레드가 block 될 시 모든 스레드가 대기해야 함(커널이 프로세스의 내부 스레드를 인식하지 못하여 해당 프로세스를 대기상태로 전환시키기 때문)

3. 혼합 스레드(N : M 매핑 방식)

  • 사용자 수준 스레드와 커널 수준 스레드를 혼합한 구조
  • 일-대-일 방식과 다-대-일 방식의 문제점을 해결하기 위해 고안

장점

  • 프로세스 내 스레드들이 병행 수행 가능
  • 사용자는 원하는 수만큼 스레드 사용
  • 효율적이면서도 유연함
  • 스레드 풀링 기법을 통해 일대일 스레드 매핑에서의 오버헤드를 줄여줌

2-2. 언어별 스레드 매핑 방식

1. PYTHON

  • 파이썬은 GIL때문에 유저레벨 스레드가 커널레벨 스레드로 n:1로 연결되어 있다.
  • 아무리 스레드를 만들어봐야 커널레벨 스레드는 하나밖에 사용하지 못하며, CPU를 동시에 하나밖에 사용하지 못한다.
  • 싱글 커널 레벨 스레드 언어 혹은 싱글코어 언어다.

2. JAVA

  • 자바는 버전마다 다르지만 최근의 유저레벨 스레드는 모두 1:1방식을 기본으로 채택하여 커널레벨 스레드와 연결된다.

3. c#

  • C#도 유저레벨 스레드는 1:1방식을 기본으로 커널레벨 스레드와 연결된다.

4. golang

  • golang은 일반적인 스레드가 아니라 경량스레드와 비슷한 역할을 하는 goroutine을 사용한다.
  • golang엔진에서 일반적인 스레드와 조금 다른방식으로 돌아간다.
  • 고루틴은 사용할 코어의 숫자를 지정하여 커널레벨스레드와 연결할 수 있다.
  • 일반적으로 네이티브 스레드가 작아도 많은 수의 고루틴을 처리할 수 있다.

2-3 JAVA의 Thread

  • 일반 스레드와 거의 차이가 없으며, JVM가 운영체제의 역할을 한다.
  • 자바에는 프로세스가 존재하지 않고 스레드만 존재하며, 자바 스레드는 JVM에 의해 스케줄되는 실행 단위 코드 블록이다.
  • 자바에서 스레드 스케줄링은 전적으로 JVM에 의해 이루어진다.
  • 아래와 같은 스레드와 관련된 많은 정보들도 JVM이 관리한다.
    • 스레드의 개수
    • 스레드로 실행되는 프로그램 코드의 메모리 위치
    • 스레드의 상태
    • 스레드의 우선순위
  • 즉, 개발자는 자바 스레드로 작동할 스레드 코드를 작성하고, 스레드 코드가 생명을 가지고 실행을 시작하도록 JVM에 요청하는 일 뿐이다.

2-4. Thread의 자원 공유

  • 스레드는 서로 프로세스의 자원을 공유하며 프로세스 실행 흐름의 일부가 되어 동시 작업을 할 수 있다.
  • 각각의 스레드는 공유의 Stack 메모리를 갖고, Code, Data, Heap은 서로가 공유하여 서로 다른 스레드에서 가져와 읽고 쓸 수 있게 된다.

2-5. Thread 스케쥴링

  • 프로세스 스케쥴링과 마찬가지로, 스레드 스케줄링(Thread Scheduling)은 운영체제에서 다중 스레드를 관리하며, CPU를 사용할 수 있는 스레드를 선택하고, CPU를 할당하는 작업을 말한다.
  • 대표적으로는 Round Robin, Priority-based scheduling, Multi-level Queue scheduling 등의 알고리즘이 있다.

2-6. Thread 상태

  1. NEW
    스레드가 생성되고 아직 호출되지 않은 상태
  1. RUNNABLE
    스레드가 실행되기 위해 기다리는 상태CPU를 할당받을 수 있는 상태이며, 언제든지 실행될 준비가 되어있다.
  1. BLOCKED
    스레드가 특정 이벤트(입출력 요청 등)가 발생하여 대기하는 상태CPU를 할당받지 못하며, 이벤트가 발생하여 다시 RUNNABLE 상태로 전환될 때까지 대기한다.
  1. TERMINATED
    스레드가 실행을 완료하고 종료된 상태더 이상 실행될 수 없으며, 메모리에서 제거된다.

2-7. Thread 상태 전이

  • 스레드의 상태 전이는 언어에 따라 다양하게 작동한다.
  • 아래는 Java에서의 스레드 상태 전이 예시이다.

2-8. TCB (Thread Control Block)

  • PCB 처럼, TCB(스레드 제어 블록)는 각 스레드마다 운영 체제에서 유지하는 스레드에 대한 정보를 담고 있는 자료구조이다.
  • 아래 그림과 같이 TCB는 PCB안에 속해 있다.

  • 스레드의 상태 정보, 스레드 ID, 스레드 우선순위, 스케줄링 정보 등 다양한 정보를 저장한다.
  • 스레드가 생성될 때 운영 체제에 의해 생성되며, 스레드가 실행을 마치고 소멸될 때 함께 소멸된다.
  • 스레드 간의 자원 공유와 동기화도 TCB를 사용하여 관리된다.(예: 뮤텍스나 세마포어와 같은 동기화 기법을 사용할 때, TCB에서 해당 스레드의 뮤텍스나 세마포어 정보를 관리하고, 스레드가 해당 자원에 대한 접근 권한을 획득하거나 반납할 때 TCB의 정보를 업데이트)

2-9. Thread 컨텍스트 스위칭

  • 프로세스 컨텍스트 스위칭과는 다르게, 하나의 프로세스 내의 스레드들을 교환한다.

Process 컨텍스트 스위칭 vs Thread 컨텍스트 스위칭

  1. TCB가 PCB 보다 가볍다.

    • 프로세스 내의 스레드들은 text, data, heap 영역 메모리를 공유하기 때문에 TCB에는 stack 및 간단한 register 포인터 정보만을 저장하기 때문에 PCB보다 TCB가 가벼워 더 빨리 읽고 쓸수 있다.
  2. 캐시 메모리 초기화 여부

    • 프로세스 컨텍스트 스위칭: 다른 프로세스의 실행으로 인해 CPU가 새로운 명령어와 데이터를 로드해야 하기 때문에 CPU 캐시 메모리를 초기화 하여야 한다.
    • 스레드 컨텍스트 스위칭: 프로세스 내 스레드 간에 스택과 레지스터 값 등 일부 컨텍스트 정보만 변경되므로 CPU 캐시 메모리는 초기화되지 않는다.
  3. 자원 동기화 문제

    • 스레드 컨텍스트 스위칭이 발생해 다른 스레드가 heap 영역의 공유 데이터에 접근할때, 이전 스레드가 이미 공유 자원을 사용하고 있는 경우 동기화 문제가 발생할 수 있다.
    • 프로세스는 기본적으로 독립된 공간이지만, IPC와 같은 공유 자원을 사용하는 경우에 똑같이 경쟁 조건이 발생 할 수가 있다.

3. Multi Process vs Multi Thread

3-1. Multi Process

장점

  • 프로그램 안정성
    • 멀티 프로세스는 각 프로세스가 독립적인 메모리 공간을 가지므로, 한 프로세스가 비정상적으로 종료되어도 다른 프로세스에 영향을 주지 않는다.
    • 프로그램 전체의 안전성을 확보할 수 있다.
  • 프로그램 병렬성
    • 멀티 프로세스와 여러개의 CPU 코어를 활용하여 둘의 시너지를 합쳐, 다중 CPU 시스템에서 각 프로세스를 병렬적으로 실행하여 성능을 향상 시킬 수 있다.
  • 시스템 확장성
    • 멀티 프로세스는 각 프로세스가 독립적이므로, 새로운 기능이나 모듈을 추가하거나 수정할때 다른 프로세스에 영향을 주지 않아 시스템의 규모를 쉽게 확장할 수 있다.

단점

  • Context Switching Overhead
    • 컨텍스트 스위칭(context switching) 과정에서 성능 저하가 올 수 있다.
    • 프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해 메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, 불러올 데이터를 준비해야 하기 때문에, 이로 인한 빈번한 Context Switching 작업으로 인해 비용 오버헤드가 발생할 수 있게 된다.
  • 자원 공유 비효율성
    • 멀티 프로세스는 각 프로세스가 독립적인 메모리 공간을 가지므로, 결과적으로 메모리 사용량이 증가하게 된다.
    • 각 프로세스간에 자원 공유가 필요할 경우 프로세스 사이의 어렵고 복잡한 통신 기법인 IPC(Inter-Process Commnuication)을 사용하여야 한다.
    • IPC는 그 자체로 오버헤드를 발생 시킨다.

3-2. Multi Thread

장점

  • 스레드는 프로세스보다 가벼움
    • 스레드는 프로세스 내에서 생성되기 때문에 스레드의 실행 환경을 설정하는 작업이 매우 간단하여 생성 및 종료가 빠르다.
    • 스레드는 프로세스와 달리, 코드, 데이터, 스택 영역을 제외한 나머지 자원을 서로 공유하기 때문에 기본적으로 내장되어 있는 데이터 용량이 프로세스보다 작다.
  • 자원의 효율성
    • 멀티 스레드는 하나의 프로세스 내에서 여러 개의 스레드를 생성되기 때문에, heap 영역과 같은 공유 메모리에 대해 스레드 간에 자원을 공유가 가능하여 IPC를 사용하지 않고도 자원 공유가 가능하다.
  • Context Switching 비용 감소
    • Thread의 컨텍스트 스위칭은 상대적으로 프로세스 컨텍스트 스위칭 오버헤드보다 훨씬 낮아 비용이 낮다.
  • 응답 시간 단축
    • 멀티 스레드는 스레드 간의 통신이나 자원 공유가 더욱 용이하며, 프로세스 보다 가벼워 컨텍스트 스위칭 오버헤드도 작아 멀티 프로세스 보다 응답 시간이 빠르다.

단점

  • 안정성 문제

    • 멀티 스레드 모델에서는 기본적으로 하나의 스레드에서 문제가 발생하면 다른 스레드들도 영향을 받아 전체 프로그램이 종료될 수 있다.
  • 동기화로 인한 성능 저하

    • 멀티 스레드 모델은 여러 개의 스레드가 공유 자원에 동시에 접근할 수 있기 때문에, 동기화 문제가 발생할 수 있다.
    • 데이터 접근을 제어하기 위해 스레드 간 동기화(syncronized)는 필수적인 기술이다.
    • 동기화 작업은 여러 스레드 접근을 제한하는 것이기 때문에 병목 현상이 일어나 성능이 저하될 가능성이 높다.
  • 데드락 (교착 상태)

    • 다수의 프로세스나 스레드가 서로 자원을 점유하고, 다른 프로세스나 스레드가 점유한 자원을 기다리는 상황에서 교착 상태가 발생할 수 있다.
  • Context Switching Overhead

    • 멀티 프로세스보다 멀티 스레드의 컨텍스트 스위칭 오버헤드가 작아 성능에 유리지만, 컨텍스트 스위칭 오버헤드 비용 자체를 무시할수는 없다.
    • 스레드 수가 많으면 많을 수록 그만큼 컨텍스트 스위칭이 많이 발생되게 되고, 성능 저하로 이어진다.
  • 디버깅이 어려움

    • 멀티 스레드를 사용하면, 여러 개의 스레드가 동시에 실행되기 때문에, 각 스레드의 동작을 추적하기 어려울 수 있다.

참고

[운영체제] 프로세스란?
👩‍💻 ‍완전히 정복하는 프로세스 vs 스레드 개념

profile
개발일지

0개의 댓글