프로세스와 스레드에 대하여
CS

프로세스와 스레드에 대하여

1. 프로세스(Process)

1) 프로세스란?

프로세스는 운영체제로부터 자원을 할당받아 실행중인 프로그램을 의미한다.

디스크에 저장된 프로그램을 실행하면 메모리가 할당되고 바이너리 코드가 메모리에 올라가게 된다.

이때, 메모리에 올라간(로드된) 프로그램의 인스턴스를 프로세스라고 부른다.

 

프로세스는 운영체제의 스케줄러가 관리하는 작업(task)의 단위로 사용되기도 한다.

스케줄러(Scheduler)
스케줄링 알고리즘에 따라 자원을 사용할 프로세스를 결정하는 운영체제의 모듈

2) 메모리 구조

프로세스가 할당받은 메모리는 4가지 영역으로 구성된다.

  • Code
    • 프로그램의 코드와 명령어가 기계어 형태로 저장되는 영역이다.
    • CPU는 이 영역에 저장된 명령어를 순차적으로 가져와서 처리한다.
    • 컴파일 시점에 메모리 크기가 결정되고 변하지 않는다.
  • Data
    • 코드에서 선언된 전역 변수 및 정적 변수가 저장되는 영역이다.
    • 컴파일 시점에 메모리 크기가 결정되고 변하지 않는다.
초기화된 변수는 Data에 저장되고 초기화되지 않은 변수는 BSS 영역에 저장된다.
  • Stack
    • 프로그램 수행에 필요한 데이터가 임시로 저장되고 자동으로 관리되는 영역이다.
    • 함수 내부에서 선언된 지역변수, 매개변수, 리턴값, 반환 시 복귀할 주소 등이 저장된다.
    • 컴파일 시점에 크기가 결정되고 런타임에 할당과 반납이 이뤄진다.
    • 함수 호출 시 메모리가 할당되고 반환 시에 반납한다.
Stack은 크기가 제한돼있어서 초과할 경우 StackOverflow가 발생한다.
  • Heap
    • 프로그래머의 필요에 따라 직접 관리되는 영역이다.
    • 런타임에 크기가 결정되며 동적으로 이 영역의 메모리를 할당하여 데이터를 저장한다.
    • 저장된 데이터는 메모리 주소 값에 의해서만 참조 및 사용된다.
    • Stack과 영역을 공유하지만 Stack은 높은 주소 값부터, Heap은 낮은 주소 값부터 할당된다.
이러한 Stack과 Heap의 메모리 할당 방식은 버퍼 오퍼 플로우를 막기 위해서이다.

3) 프로세스의 상태

프로세스는 상태가 변경되며 수행된다.

  • Running : CPU를 사용중인 상태
  • Ready : CPU를 사용하기 위해 기다리고 있는 상태
  • Waiting : 프로세스가 요청한 I/O를 기다리는 등 CPU를 점유해도 사용할 수 없는 상태
  • New : 디스크에서 메모리로 로드되어 실행할 준비를 하는 상태
  • Terminated : 프로세스의 수행이 종료된 상태
New와 Terminated는 프로세스가 실행 및 종료될 때 임시적으로 머무르는 상태이다.

2. 컨텍스트 스위칭(Context Switching)

1) 개요

컨텍스트는 OS 관점에서 CPU가 프로세스를 실행하기 위해 필요한 프로세스의 정보를 뜻한다.

컨텍스트 스위칭은 CPU가 실행중인 프로세스(컨텍스트)를 교체(스위칭)하는 것을 의미한다.

 

특정 프로세스가 CPU를 사용중인 상태에서 더 높은 우선순위의 프로세스를 실행해야 할 때,

기존 프로세스의 정보를 저장하고 새로운 프로세스의 정보로 교체하는 컨텍스트 스위칭이 발생한다.

 

타이머, I/O 등의 인터럽트에 의해 CPU 제어권이 운영체제 커널에게 넘어가게 되면

운영체제는 CPU 레지스터에 저장돼있는 기존 프로세스의 컨텍스트를 PCB에 저장하고,

새로운 프로세스의 PCB로부터 저장된 컨텍스트를 가져오는 과정을 거친다.

CPU가 마치 여러 프로세스를 동시에 실행하는 것처럼 보이지만,
사실은 컨텍스트 스위칭을 통해 빠르게 여러 프로세스를 번갈아 실행하고 있는 것이다.

2) PCB(Process Control Block)

PCB 구조

PCB는 프로세스를 제어하기 위한 정보를 포함하는 운영체제 커널 내부의 자료구조이다.

운영체제가 프로세스를 표현한 것으로, 실행중이던 프로세스의 상태를 스냅샷 형태로 저장하는 공간이다.

프로세스가 생성될 때 고유의 PCB가 생성되며 프로세스가 종료될 때 함께 제거된다.

 

저장되는 정보에는 다음 목록이 포함된다.

  • 프로세스 ID, 프로세스 상태
  • PC(Program Counter), SP(Stack Pointer) 등 레지스터 관련 정보
  • 메모리 사이즈 등 메모리 관련 정보

프로그램 카운터와 스택 포인터는 컨텍스트 스위칭을 가능하게 하는 핵심 정보다.

프로그램 카운터(PC)와 스택 포인터(SP)
CPU가 외부의 요청을 처리하기 위해 데이터를 임시로 저장하는 고속 기억 장치(레지스터)이다.
프로그램 카운터는 CPU가 다음에 실행할 명령어를 가리키는 주소 값을 가지고,
스택 포인터는 스택의 마지막 위치를 가리키는 주소 값을 가진다.

3) 과정

Running 상태의 A 프로세스와 Ready 상태의 B 프로세스가 있다고 가정하자.

  1. A 프로세스의 CPU 사용시간이 끝나 타이머 인터럽트가 발생
  2. 스케줄러에 의해 선택된 B 프로세스를 실행하기 위해 운영체제가 CPU 제어권 획득
  3. 운영체제는 CPU 내부 레지스터인 PC, SP에 저장된 값을 A 프로세스의 PCB에 저장
  4. A 프로세스가 Ready 또는 Waiting 상태로 변경되고 B 프로세스의 PCB로부터
    PC, SP 값을 가져와 레지스터에 저장
  5. CPU가 B 프로세스를 실행하여 상태가 Ready에서 Running으로 변화
5번 과정에서 프로세스의 준비 상태가 실행 상태로 변화하는 것을 디스패치(Dispatch)라고 한다.
시스템 콜 또는 인터럽트에 의해 CPU 제어권이 넘어갔다고 해서 컨텍스트 스위칭이 일어났다고 볼 수는 없다.
Ex) 단순히 커널 모드에서 운영체제의 코드(인터럽트 처리 루틴 등)를 실행하는 경우

4) 오버헤드(Overhead)

두 프로세스 사이의 컨텍스트 스위칭

오버헤드는 작업을 처리하는데 드는 간접적인 자원(주로 시간과 메모리)을 의미하는데,

컨텍스트 스위칭 과정에서 PCB에 컨텍스트를 저장하고 가져오는 동안 CPU는 작업을 수행하지 못한다.

 

컨텍스트 스위칭이 과도하게 일어나면 오버헤드 비용을 발생시켜 성능 저하의 원인이 된다.

빠른 실행을 위해 컨텍스트 스위칭 코드는 어셈블리어로 되어있는 경우가 많다.

3. 스레드(Thread)

1) 개요

프로세스가 작업(task)의 단위라면 스레드는 작업을 실행하는 흐름의 단위이며,

프로세스는 최소 하나의 스레드(메인 스레드)를 갖고 있다.

2) 프로세스와 스레드의 차이

스레드는 운영체제의 스케줄러에 영향을 받지 않고 독립적으로 관리되는 가장 작은 명령어 시퀀스이다.

스레드는 프로세스에 할당된 자원을 이용하기 때문에 다른 스레드와 자원을 공유한다는 특징이 있다.

 

운영체제는 각 프로세스마다 독립적인 메모리 영역(Code, Data, Stack, Heap)을 할당해주기 때문에

프로세스는 다른 프로세스의 정보에 접근할 수 없지만,

 

스레드는 독립적인 메모리를 Stack 형식으로만 할당받고 나머지 영역은 프로세스의 메모리를 사용하기 때문에

각 스레드는 공유된 프로세스의 메모리 영역에 접근하여 서로 데이터를 읽고 쓸 수 있다.

스레드는 작업 실행 흐름을 나타내므로 CPU 입장에서 스레드는 최소 작업 단위이다.
하지만 운영체제 입장에서 최소 작업 단위는 프로세스이므로 스케줄링 및 자원 할당은 프로세스에만 이뤄진다.
프로세스는 다수의 스레드를 가질 수 있으므로 같은 프로세스에 소속된 스레드끼리 자원을 공유할 수 밖에 없다.

3) 메모리 구조

스레드는 스레드 ID, 프로그램 카운터, 레지스터 세트, Stack 영역을 독립적으로 가지고

Code, Data, Heap 메모리 영역 등 정보를 다른 스레드와 공유한다.

4) 멀티스레딩(Multi-Threading)

하나의 프로세스(작업)를 다수(두 개 이상)의 스레드를 사용해 처리하는 것을 의미한다.

 

싱글코어에서는 컨텍스트 스위칭을 통해 각 스레드를 번갈아 실행하는 동시성을 만족하고

멀티코어에서는 여러 스레드를 병렬적으로 처리하는 병렬성을 만족한다.

멀티태스킹과 멀티프로세싱
흔히 말하는 멀티태스킹은 하나의 운영체제에서 다수의 프로세스를 동시에 실행하는 것을 의미하는데,
여기서의 동시는 동시성(Concurrency)을 뜻하고 스케줄링 방식을 통해 알 수 있다.
멀티프로세싱은 멀티프로세서 환경에서 다수의 프로세스를 병렬적으로 처리하는 것을 말한다.

멀티스레딩이 갖는 장단점은 다음과 같다.

  • 장점
    • 멀티스레딩은 각 스레드가 메모리를 공유하기 때문에 그 만큼 메모리 자원을 아낄 수 있다.
    • 컨텍스트 스위칭 시 컨텍스트의 크기가 작으므로 비용이 적다.
    • 공유 메모리(Data, Heap)을 활용해 스레드 간 통신이 간단하여 응답 속도가 빠르다.
  • 단점
    • 하나의 스레드가 발생시킨 문제가 다른 모든 스레드에게 영향을 줄 수 있다.
    • 여러 스레드가 동시에 공유 메모리에 접근할 수 있기 때문에 동기화 문제가 발생할 수 있다.
동기화 문제 (Synchronization Issue)
여러 스레드에서 특정한 하나의 자원(전역 변수 등)을 함께 사용할 때 발생할 수 있는 문제를 의미한다.

운영체제는 스레드를 스케줄링 하지 않으므로 각 스레드가 자원을 사용할 순서를 결정해주지 않는다.
즉, A 스레드에서 사용할 자원이 B 스레드에 의해 수정되어 A 스레드가 원하지 않는 결과를 얻을 수도 있다는 의미이다.

프로그래머는 동기화 문제가 발생하지 않도록 신중하게 프로그램을 설계해야 한다.
(멀티스레딩에서 각 스레드가 원하는 실행 결과를 얻는 것을 보장할 때 Thread-Safe 하다고 말한다.)

참고 문서

[운영체제] 프로세스와 스레드

콘텍스트 스위칭

운영체제: 콘텍스트 스위칭

콘텍스트 스위칭은 무엇인가?

인터럽트의 개념과 종류

스택과 힙을 나눈 이유

스택 메모리 크기가 제한된 이유?

프로세스 메모리 구조

프로세스의 메모리 구조

물리 메모리와 가상 메모리, 메모리 구조에 대해

멀티스레딩 - 위키백과

멀티코어와 멀티스레드