main

프로세스와 스레드 II

Log
25

프로세스 & 스레드의 동시 실행 원리

우리가 음악을 들으면서, 웹서핑을 하고, 메신저의 메시지를 확인할 수 있는 이유는 컴퓨터 내부적으로 프로세스와 스레드를 동시에 처리하는 멀티 태스킹(multi tasking)Visit Website 기술 때문입니다. 하지만 여기서 동시에 처리한다는 것이 심플하게 CPU 프로세서가 프로그램들을 한꺼번에 동시에 돌리는 것으로 생각하겠지만, 내부적으로 복잡한 원리에 의해 처리가 됩니다.

231006-103808


멀티코어와 스레드

컴퓨터 견적을 맞추다 보면 4코어 8스레드 CPU에 대한 단어를 본적이 있으신가요?
231006-104242

CPU는 한개는 여러개의 코어를 가질 수 있습니다. 4코어가 물리적 코어 갯수면, 8쓰레드는 논리적 코어 갯수를 말합니다. 쉽게 말해 코어는 실제 CPU에서 일을 처리하는 부분이고, CPU 코어가 실제 일을 처리하는 부분이라고 하면 CPU 스레드는 코어가 처리하는 일의 흐름이라고 보면 됩니다. 이 경우 물리적 코어 하나가 스레드 두 개 이상을 동시에 실행 가능하다는 의미가 됩니다. 즉, 운영체제가 8개의 작업을 동시에 처리할 수 있다는 뜻입니다. 이를 하이퍼스레딩(Hyper-Threading) 기술이라 말합니다.
쓰레드가 많을 수록 병렬적인 작업을 처리하는데 유리합니다.
231006-104727

단, 여기서 CPU의 쓰레드는 앞서 이야기한 프로세스의 쓰레드와는 조금 다른 개념입니다. 엄밀히 말하자면 CPU의 스레드는 하드웨어적 스레드이고 프로그램의 스레드는 소프트웨어적 스레드로 구분합니다.


CPU의 작업 처리 방식

병렬성 (Parallelism)

병렬성은 직관적으로 명령어를 메모리에서 뽑아 해석하고 실행하는 반도체 유닛인 여러개의 코어에 맞춰 여러개의 프로세스, 스레드를 돌려 병렬로 작업들을 동시 수행하는 것을 말합니다.
231006-105213
듀얼코어, 쿼드코어, 옥타코어 등등 이런 명칭이 붙는 멀티코어 프로세서가 달린 컴퓨터에서 할 수 있는 방식입니다.


동시성 (Concurrency)

동시성은 둘 이상의 작업이 동시에 실행되는 것을 의미합니다. 이 '동시' 라는 의미에서 병렬성과 동시성의 한글 의미가 헷갈릴수 있습니다. Parallelism가 물리적으로 정말로 동시에 실행하는 것이라고 하면, Concurrency는 동시에 실행하는 것처럼 보이게 하는 것으로 이해하면 됩니다.

즉, 1개의 코어가 있고 4개의 작업이 있다고 가정하다면, 아래 그림과 같이 프로세스들을 ​계속 번갈아가면서 조금씩 처리함으로써 마치 프로그램이 동시에 실행되는 것 처럼 보이는 것입니다. 이때 프로세스들을 ​번갈아가면서 매우 빠르게 처리하기 때문에 컴퓨터를 모르는 사람들이 보면 마치 동시에 돌아가는 것처럼 보이게 됩니다.

단, 이때 작업들을 번갈아가면서 실행할때 작업들을 아주 잘게 나누어 아주 조금씩만 작업을 수행하고 다음 작업으로 넘어가는 식으로 동작됩니다. 이렇게 하는 이유는 여러 작업을 동시에 처리하는 것처럼 보이게 만들어, 사용자에게 더 빠른 반응성을 제공하기 위해서입니다. 그리고 이렇게 진행 중인 작업들을 A → B → C → D 로 번갈아 바꾸는 것을 Context Switching(문맥교환)이라고 부릅니다.


프로세스의 컨텍스트 스위칭이 이뤄지는 원리

CPU는 한 번에 하나의 프로세스만 실행할 수 있으므로, 여러 개의 프로세스를 번갈아가며 실행하여 CPU 활용률을 높이기 위해 컨텍스트 스위칭이 필요하게 됩니다.

그럼 컨텍스트 스위칭은 어떤 원리로 관리가 되는걸까요?

컨텍스트 스위칭을 좀더 구체적으로 말하자면, 동작 중인 프로세스가 대기를 하면서 해당 프로세스의 상태(Context)를 보관하고, 대기하고 있던 다음 순서의 프로세스가 동작하면서 이전에 보관했던 프로세스의 상태를 복구하는 작업을 말합니다. 이러한 컨텍스트 스위칭이 일어날 때 다음번 프로세스는 스케줄러가 결정하게 됩니다. 즉, 컨텍스트 스위칭을 하는 주체는 스케줄러입니다.


PCB (Process Control Block)

PCB(프로세스 제어 블록)는 운영체제에서 프로세스를 관리하기 위해 해당 프로세스의 상태 정보를 담고 있는 자료구조를 말합니다.

프로세스를 컨텍스트 스위칭 할때 기존 프로세스의 상태를 어딘가에 저장해 둬야 다음에 똑같은 작업을 이어서 할 수 있을 것이고, 새로 해야 할 작업의 상태 또한 알아야 어디서부터 다시 작업을 시작할지 결정할 수 있습니다. 즉, PCB는 프로세스 스케줄링을 위해 프로세스에 관한 모든 정보 저장하는 임시 저장소라고 할 수 있습니다.


프로세스 스케줄링

프로세스 스케줄링(Process Scheduling)은 운영체제에서 CPU를 사용할 수 있는 프로세스를 선택하고, CPU를 할당하는 작업을 말합니다. 프로세스 스케줄링은 프로세스의 우선순위, 작업량 등을 고려하여 효율적으로 배치하여, 이를 통해 운영체제는 CPU를 효율적으로 사용하며 시스템 전반적인 성능을 향상시킬 수 있습니다. 그래서 스케줄링은 멀티 태스킹 작업을 만들어내는 데에 있어서 핵심적인 부분입니다.

스케쥴링은 운영체제의 특징과 시스템 요구사항에 따라 다양한 알고리즘 방식으로 동작됩니다. 알고리즘 종류로는 대표적으로 FCFS(First-Come, First-Served), SJF(Shortest-Job-First), Priority, RR(Round-Robin), Multilevel Queue 등이 있습니다.

231006-112426

프로세스는 아래와 같이 고유한 상태를 갖습니다. 프로세스가 생성되어 실행하기 까지 프로세스는 여러 상태를 갖게 되고, 상태 변화에 따라서 프로세스가 동작하게 됩니다. 프로세스는 일반적으로 5가지의 상태가 있습니다.

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

운영체제는 프로세스의 상태를 감시하고, 프로세스 상태를 기반으로 프로세스 스케쥴링을 통해 프로세스를 관리하고 제어한다.
예시로 준비단계에 있는 여러 프로세스 중에서 어떤 프로세스를 실행 단계로 바꿀지, 종료 단계에 있는 프로세스를 제거하고 준비단계에 있는 다른 프로세스를 선택할 건지 스케쥴링 알고리즘에 의해 동작됩니다.
231006-113055


원리

따라서 프로그램이 실행되면 프로세스가 생김과 동시에, PCB가 같이 생성됩니다. PCB를 통해서 실행 상태를 파악하고 우선순위를 조정하며, 스케줄링을 수행하고, 다른 프로세스와의 동기화를 제어합니다.
231006-113207

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

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

Context Switching 과정

231006-113642

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

이러한 컨텍스트 스위칭 과정은 사용자에게 빠른 반응성과 동시성을 제공하지만, 실행되는 프로세스의 변경 과정에서 프로세스의 상태, 레지스터 값 등이 저장되고 불러오는 등의 작업이 수행하기 때문에 시스템에 많은 부담을 주게됩니다.
231006-115034
위의 컨텍스트 스위칭 과정 그림을 보면 P1이 Execute에서 idle이 될 때 P2가 바로 Execute가 되지 않고 idle을 상태에 조금 있다가 Execute가 되는걸 볼 수 있습니다. 이 간극이 바로 컨텍스트 스위칭 오버헤드(overhead) 인 것입니다.

컨텍스트 스위칭 오버헤드는 대표적으로 다음과 같은 행위에 의해서 발생된다.

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

컨텍스트 스위칭 과정에서 PCB를 저장하고 복원하는데 비용이 발생하며, 프로세스 자체가 교체되는 것이니 CPU의 캐시 메모리에 저장된 데이터가 무효화가 됩니다. 이 과정에서는 메모리 접근 시간이 늘어나고, 성능 저하가 발생할 수 있다. 또한 CPU 스케줄링 알고리즘에 따라 프로세스를 선택하는 비용도 만만치 않습니다.

바로 뒤에서 다루겠지만, 컨텍스트 스위칭은 꼭 프로세스 뿐만 아니라 여러개의 스레드들 끼리도 스위칭이 일어나게 됩니다. 보통 멀티 스레드라고 하면 여러개의 스레드가 동시에 돌아가니 프로그램 성능이 무조건 상승할거라 예상하지만, 이는 정확하지 않습니다. 컨텍스트 스위칭 오버헤드라는 변수 때문에 스레드 교체 과정에서 과하게 오버헤드가 발생하면 오히려 멀티 스레드가 싱글 스레드보다 성능이 떨어지는 현상이 나타날수 있기 때문입니다.


스레드 스케줄링

프로세스 스케쥴링이 있는 것처럼, 스레드도 스케쥴링이 존재합니다. 스레드 스케쥴링은 운영체제에서 다중 스레드를 관리하며, CPU를 사용할 수 있는 스레드를 선택하고, CPU를 할당하는 작업을 말합니다.

스레드 스케쥴링은 프로레스 스케쥴링과 비슷한 알고리즘을 가지고 유사하게 동작합니다.
다만, 스레드 스케쥴링은 프로세스 스케쥴링과 다르게 하나의 프로세스 내에서 다수의 스레드가 동작하는 형태이기 때문에 스레드 간의 상호작용과 동기화 문제를 고려해야한다는 점이 있습니다.

231009-111931


스레드 상태

프로세스 PCB에 상태가 기록되는 것처럼, 스레드도 TCB가 존재하며 각 TCB마다 상태가 존재합니다.

  • 스레드 상태
    • NEW: 스레드가 생성되고 아직 호출되지 않은 상태
    • RUNNABLE: 스레드가 실행되기 위해 기다리는 상태. CPU를 할당받을 수 있는 상태이며, 언제든지 실행될 준비가 됨.
    • BLOCKED: 스레드가 특정 이벤트(입출력 요청 등)가 발생하여 대기하는 상태. CPU를 할당받지 못함
    • TERMINATED: 스레드가 실행을 완료하고 종료된 상태

스레드 컨텍스트 스위칭

스레드 컨텍스트 스위칭(thread context switching)은 멀티 스레딩 환경에서 스레드 간의 실행을 전환하는 기술입니다.프로세스 컨텍스트 스위칭과 다른점은 스레드 컨텍스트 스위칭은 하나의 프로내스 내의 스레드들을 교환한다는 점입니다.

231009-112329


TCB (Thread Control Block)

PCB 처럼, TCB(스레드 제어 블록)는 각 스레드마다 운영 체제에서 유지하는 스레드에 대한 정보를 담고 있는 자료구조이다. 그림에서 볼 수 있듯이 TCB는 PCB 안에 들어있다. 스레드가 프로세스 내에 위치한 것 처럼 말입니다.

231009-112357

역시 스레드의 상태 정보, 스레드 ID, 스레드 우선순위, 스케줄링 정보 등 다양한 정보를 저장하게 됩니다. TCB도 스레드가 생성될 때 운영 체제에 의해 생성되며, 스레드가 실행을 마치고 소멸될 때 함께 소멸됩니다. 또한 스레드 간의 자원 공유와 동기화도 TCB를 사용하여 관리합니다.


프로세스 컨텍스트 스위칭 vs 스레드 컨텍스트 스위칭

프로세스 컨텍스트 스위칭과 스레드 컨텍스트 스위칭은 모두 멀티태스킹 환경에서 여러 프로세스 또는 스레드를 동시에 실행하기 위한 기술입니다. 그러나 두 기술은 몇 가지 차이점이 있습니다.

  • TCB가 PCB보다 가볍다
    결론부터 말하자면, 스레드 컨텍스트 스위칭이 프로세스 컨텍스트 스위칭보다 더 빠릅니다.
    위에서 프로세스와 스레드의 메모리 섹션에서 다뤘듯이, 프로세스 내의 스레드들은 text, data, heap 영역 메모리를 공유하기 때문에 TCB에는 stack 및 간단한 register 포인터 정보만을 저장하기 때문에 PCB보다 TCB가 가벼워 더 빨리 읽고 쓸수 있습니다.

  • 캐시 메모리 초기화 여부
    CPU 캐쉬 메모리는 CPU와 메인 메모리 사이에 위치하며 CPU에서 한번 이상 읽어들인 메모리의 데이터를 저장하고 있다가, CPU가 다시 그 메모리에 저장된 데이터를 요구할 때, 메인 메모리를 통하지 않고 곧바로 데이터를 전달해 주는 용도입니다.
    즉, 쉽게 말하면 컴퓨터가 일을 하기 위해서 자주 쓸 것 같은 물건들을 서랍에 꺼내서 책상에 올려 놓는 것입니다. 책상에 올려져있으니 바로바로 쉽게 들어 데이터를 사용할 수 있게 됩니다.

231009-112927

그런데 프로세스 컨텍스트 스위칭이 일어날 경우, 다른 프로세스의 실행으로 인해 CPU가 새로운 명령어와 데이터를 로드해야 하기 때문에 CPU 캐시 메모리를 초기화 하여야 합니다. 이것이 프로세스 컨텍스트 스위칭에 부담이 되는 요소입니다.

스레드 컨텍스트 스위칭일 경우, 프로세스 내 스레드 간에 스택과 레지스터 값 등 일부 컨텍스트 정보만 변경되므로 CPU 캐시 메모리는 초기화되지 않습니다.

  • 자원 동기화 문제
    스레드 컨텍스트 스위칭이 발생해 다른 스레드가 heap 영역의 공유 데이터에 접근할때, 이전 스레드가 이미 공유 자원을 사용하고 있는 경우 동기화 문제가 발생할 수 있습니다.

멀티스레드를 사용하면 각각의 스레드 중 어떤 것이 어떤 순서로 실행될지 그 순서를 알 수 없습니다. 만약 A 스레드가 어떤 자원을 사용하다가 B 스레드로 제어권이 넘어간 후 B 스레드가 해당 자원을 수정했을 때, 다시 제어권을 받은 A 가 해당 자원에 접근하지 못하거나, 바뀐 자원에 접근하게 되는 오류가 발생할 수 있습니다.

이처럼 여러 스레드가 함께 전역 변수를 사용할 경우 발생할 수 있는 충돌을 동기화 문제라고 합니다. 스케줄링은 운영체제가 자동으로 해주지 않기 때문에 프로그래머가 적절한 기법을 직접 구현해야 하므로 프로그래밍할 때 멀티스레드를 사용하려면 신중해야 합니다.


Multi Process 와 Multi Thread

멀티 프로세스와 멀티 스레드는 한 어플리케이션에 대한 처리방식 이라고 보면 됩니다.

예상할 수 있듯이, 프로세스와 스레드가 단일이 아닌 다중으로 돌아감으로써 성능 향상 등 여러가지 효과를 얻을 수 있게 됩니다. 하지만 또한 이로 인해 발생되는 부가적인 문제점도 발생하게 됩니다. 따라서 각각의 장단점을 파악하여 적재적소에 사용하는 것이 요구됩니다.


Reference Doc

완전히 정복하는 프로세스 vs 스레드 개념


김다은 이모지
Daeun Kim
Junior Frontend Engineer