CS - 프로세스와 스레드

한민우·2024년 11월 5일

CS

목록 보기
11/11

프로세스 (Process)

정의

  • 실행 중인 프로그램
  • 하나의 프로세스는 실행을 위해 독립된 메모리 공간을 할당받는다.
  • 각 프로세스는 운영체제에 의해 독립적으로 관리되며, 하나의 프로그램이 여러 프로세스를 생성할 수 있다.

프로세스의 구조

프로세스는 운영체제에서 실행되는 동안, 특정한 메모리 구조를 가진다. 프로세스의 메모리 공간은 다음과 같이 나눌 수 있다.

1. 텍스트 세그먼트 (Text Segment, 코드 세그먼트)

  • 역할: 프로그램의 실행 코드를 저장한다. CPU가 실행할 명령어들이 위치하는 곳
  • 특징
    • 읽기 전용: 작성된 코드가 기계어로 변환되어 텍스트 세그먼트에 저장된다.
    • CPU는 텍스트 세그먼트에서 저장된 명령을 가져와 실행한다.
  • 예시: 프로그램이 실행되면 add 함수의 실제 코드는 텍스트 세그먼트에 저장된다. 함수 자체의 명령어들이 텍스트 세그먼트에 저장되고 CPU는 이 코드를 하나씩 실행한다.
function add(a, b) {
  return a + b;
}

2. 데이터 세그먼트 (Data Segment)
크게 두 가지로 나누어진다. 초기화된 데이터 / 초기화되지 않은 데이터

a) 초기화된 데이터 세그먼트 (Initialized Data Segment)

  • 역할: 초기화된 전역 변수나 정적 변수를 저장한다.
  • JavaScript의 전역 변수, 모듈 내의 상수나 전역 스코프에서 정의된 값, 다른 언어의 static 변수
  • 예시: globalValue는 프로그램이 시작되기 전에 초기화된 데이터이다. globalValue는 전역에 존재하고, 텍스트 세그먼트에 저장된 코드와 함께 프로그램이 실행될 때 초기화된다.
const glovalValue = 42;
function showValue() {
  console.log(globalValue);
}
showValue();

b) 초기화되지 않은 데이터 세그먼트 (BSS Segment, Block Started By Symbol Segment)

  • 역할: 초기화되지 않은 전역 변수 또는 정적 변수를 저장한다.
  • 개발자가 선언만 하고 초기화하지 않은 전역변수 등이 포함된다.

3. 스택 세그먼트 (Stack Segment)

  • 역할: 함수 호출 시 생성되는 지역 변수와 매개변수를 저장한다. 함수가 호출될 때마다 스택 프레임이 만들어지고 함수가 반환되면 스택에서 해당 프레임이 제거된다.
  • 특징: 스택은 함수 호출이 끝나면 자동으로 메모리가 해제된다.
  • 스택 오버플로우: 함수가 너무 많이 중첩 호출되었을 때 발생할 수 있다. 예를 들어, 재귀 호출이 종료 조건 없이 이루어지면 스택 오버플로우가 발생할 수 있다.
function recursive() {
  return recursive(); // 종료 조건이 없어서 무한으로 호출됨
}
recursive();

4. 힙 세그먼트 (Heap Segment)

  • 역할: 동적 메모리 할당이 이루어지는 공간이다. JavaScript에서는 주로 객체(Object), 배열(Array), 함수(Closure) 같은 참조 타입들이 힙에 저장된다.
  • C/C++의 malloc, calloc, new 같은 함수나 연산자를 통해 할당한 메모리 공간이 힙에 저장된다.
  • 특징: 힙은 스택과 달리 수명이 관리되지 않기 때문에 메모리 누수가 발생할 수 있다. Garbage Collector가 메모리를 정리해주지만, C/C++의 경우 GC가 없기 때문에 개발자가 직접 관리해야 한다.
  • 예시: 힙에 데이터(정수 값)가 저장되고, delete 함수로 직접 메모리를 해제한다.
#include <iostream>

int main() {
    // 정수형 변수 하나를 힙에 동적 할당
    int* p = new int;   // new 키워드를 통해 int 타입 메모리 공간 할당
    
    *p = 1220;            // 할당된 메모리에 값 저장

    delete p;           // 사용 후 메모리 해제
    p = nullptr;        // 해제 후 포인터 초기화 
}

프로세스의 특징

  • 독립된 실행 단위: 각 프로세스는 독립적인 주소 공간을 갖는다.
  • 프로세스 간 통신(IPC): 프로세스 간 데이터를 주고받기 위해서는 운영체제의 도움을 받아야 하며, 이를 프로세스 간 통신(Inter-process Communication, IPC)이라고 한다. IPC의 방식에는 파이프, 메시지 큐, 공유 메모리 등이 있다.
  • 컨텍스트 스위칭: 운영체제는 멀티태스킹을 지원하기 위해 여러 프로세스를 빠르게 전환하는데, 이를 컨텍스트 스위칭이라고 한다. 각 프로세스의 상태를 저장하고 복원하는 과정에서 오버헤드가 발생할 수 있다.

스레드 (Thread)

정의

  • 프로세스 내에서 실행의 흐름을 담당하는 단위
  • 하나의 프로세스에는 하나 이상의 스레드가 존재할 수 있으으며, 이들은 같은 메모리 공간을 공유한다.
  • 프로세스의 경량화된 실행 단위로 볼 수 있음

스레드의 구조

스레드는 같은 프로세스의 메모리 공간을 공유하지만, 각각 독립적인 스택을 가진다.
스레드 간에는 다음 메모리 공간을 공유한다:
1. 텍스트 세그먼트: 스레드는 프로세스의 코드를 공유한다.
2. 데이터 세그먼트: 전역 변수와 정적 변수를 공유한다.
3. 힙: 동적으로 할당된 메모리를 공유한다

스레드의 특징

  • 가벼운 실행 단위: 스레드는 같은 프로세스 내에서 자원을 공유하기 때문에 스레드 간 전환은 프로세스 간 전환보다 오버헤드가 적다. 즉, 컨텍스트 스위칭이 더 빠르게 이루어진다.
  • 동기화 문제: 스레드들은 같은 메모리 공간을 공유하기 때문에 동시성 문제가 발생할 수 있다.
    두 스레드가 동시에 같은 메모리 위치에 접근하면 경쟁 상태(Race Condition)가 발생할 수 있다. 이를 방지하기 위해 락(lock)이나 세마포어(semaphore)같은 동기화 기법이 필요하다.
  • 병렬 처리: 현대의 CPU는 멀티코어로 구성되어 있어 여러 스레드를 병렬로 실행할 수 있다.

스레드의 예시

JavaScript는 싱글 스레드 언어로 알려져 있지만, 사실 JavaScript 엔진은 비동기 작업을 처리할 때 이벤트 루프를 사용하여 논리적인 동시성을 구현한다.
하지만 Node.js에서는 worker_threads 모듈을 사용하여 실제로 여러 스레드를 생성할 수 있다.

프로세스와 스레드의 차이점

특징프로세스스레드
정의실행 중인 프로그램의 인스턴스프로세스 내에서 실행의 흐름을 담당하는 단위
메모리 공간독립적인 메모리 공간을 가짐같은 프로세스 내에서 메모리를 공유함
통신 방식프로세스 간 통신은 IPC를 사용스레드는 메모리를 공유하므로 통신이 더 빠름
컨텍스트 스위칭 비용컨텍스트 스위칭 비용이 큼컨텍스트 스위칭 비용이 적음
오버헤드각 프로세스는 독립적이므로 오버헤드가 큼스레드는 경량화되어 오버헤드가 적음
동시성 문제독립적이므로 동시성 문제 발생이 적음메모리를 공유하므로 동기화 기법이 필요함
실행 단위프로세스는 독립적인 실행 단위임스레드는 프로세스의 경량화된 실행 단위임

현대 시스템에서의 프로세스와 스레드

멀티프로세싱 (Multiprocessing)

  • 멀티프로세싱은 여러 CPU 코어에서 여러 프로세스를 동시에 실행하는 것을 의미한다. 각 프로세스는 독립적인 주소 공간을 가지므로 메모리 충돌이 없다.
  • 주로 CPU 집약적 작업을 처리할 때 적합하다.
  • 운영체제에서 멀티태스킹을 구현하는 방식이기도 하다. 예를 들어, 사용자는 한 화면에서 여러 프로그램을 동시에 실행할 수 있다.

멀티스레딩 (Multithreading)

  • 멀티스레딩은 하나의 프로세스 내에서 여러 스레드를 병렬로 실행하는 것을 의미한다. 스레드 간의 메모리 공유로 인해, 성능 향상과 더 적은 자원 소모를 기대할 수 있다.
  • 주로 I/O 집약적 작업에서 많이 사용된다. 예를 들어, 웹 서버는 수많은 요청을 동시에 처리해야 하기 때문에 스레드를 활용하여 비동기적으로 처리하는 것이 일반적이다.
profile
예비 게임서버 개발자

0개의 댓글