프로세스와 스레드

koreanhole·2021년 5월 3일
1

프로세스

컴퓨터에서 연속적으로 실행되는 컴퓨터 프로그램을 말한다. 프로그램은 저장장치에 저장된 코드를 말하며 프로세스는 이를 구동하여 프로그램과 상태가 메모리 상에서 실행되는 작업 단위를 말한다. 프로그램이 실행되기 위해서운영체제로 부터 독립된 메모리 영역을 할당 받아야 한다.(Code, Data, Stack, Heap)

우리는 보통 동시에 여러 프로그램(프로세스)를 실행한다. 겉으로 보이기에는 동시에 실행되고 관리되는것처럼 보이지만 동시는 아니다. CPU는 한번에 한개의 명령어만 실행할 수 있다. CPU는 재빠르게 여러 프로세스들을 번갈아가며 실행하고 관리하고 있는 것이다. CPU는 매우 빠르기 때문에 우리는 동시에 처리되고 있다고 느낄 뿐이다. CPU가 여러 프로세스들을 번갈아가며 처리하는 것을 Context Switching(문맥교환)이라고 한다.

프로세스의 메모리 영역

  • Code영역
    • 실행할 프로그램의 코드나 명령어들이 기계어 형태로 저장되는 영역이다. CPU는 코드영역에 저장된 명령어들을 하나씩 처리한다.
  • Data영역
    • 코드에서 선언한 전역 변수와 정적 변수가 저장되는 영역이다. 프로그램이 실행되면서 할당되고 종료되면서 소멸된다.
  • Stack영역
    • 함수 안에서 선언된 지역변수, 매개변수, 리턴값등이 저장된다. 함수 호출시 기록되고 종료되면 제거된다.
  • Heap영역
    • 관리가 가능한 데이터 이외의 다른 형태의 데이터를 관리하기 위한 자유 공간(Free Space)이다.

Context Switching

하나의 프로세스가 이미 CPU를 사용중인 상태에서 다른 프로세스가 CPU를 사용하기 위해 이전 프로세스의 상태를 저장하고 새로운 프로세스의 상태를 적재하는 것을 말한다. 여러 프로세스의 효과적인 문맥교환을 통해 멀티태스킹을 할 수 있다. 이와 같은 문맥교환은 Scheduler에 의해 발생한다. 스케쥴러는 효율적인 CPU사용을 도와준다.

위의 프로세스 문맥 교환을 나타내는 그림을 보자. 프로세스 P0는 실행, P1는 대기 상태이다. 인터럽트나 시스템 콜에 의해 운영체제는 P0의 상태를 대기 상태로 전환하면서 프로세스에 대한 정보를 PCB0에 저장한다. 이후 P1이 실행될 순서가 되면 운영체제는 PCB1에서 P1에 대한 정보를 복원하며 P1의 상태를 실행 상태로 전환한다. 이후 문맥 교환에 의해 P1의 상태는 다시 PCB1에 저장되고 P1은 대기 상태로 전환된다.

PCB

PCB(Process Control Block)은 운영체제가 프로세스를 표현한 자료구조이다. 특정 프로세스에 대한 정보를 갖고 있다. 각 프로세스가 생성될 때마다 고유의 PCB가 생성되고 프로세스가 완료되면 PCB는 제거된다. 프로세스간 문맥교환이 일어나면서 프로세스는 진행하던 작업들을 PCB에 저장하고 이후에 자신의 순서가 왔을 때 이를 이어서 처리한다. PCB에는 다음과 같은 프로세스의 정보가 저장된다.

  • 프로세스 식별자(Process ID)
  • 프로세스 상태(Process State): 생성(create), 준비(ready), 실행(running), 대기(waiting), 완료(terminated)
  • 프로그램 계수기(Program Counter): 프로세스가 다음에 실행할 명령어의 주소를 가리킨다.
  • CPU 레지스터 및 일반 레지스터
  • CPU 스케쥴링 정보: 우선 순위, 최종 실행시각, CPU점유 시간
  • 메모리 관리 정보: 프로세스의 주소 공간
  • 프로세스 계정 정보: 페이지 테이블, 스케쥴링 큐 포인터, 소유자, 부모
  • 입출력 상태 정보
  • 포인터: 부모프로세스, 자식 프로세스, 프로세스가 위치한 메모리 주소에 대한 포인터, 할당된 자원에 대한 포인터

프로세스의 생명주기

프로세스는 생성되어 종료되기 전까지 항상 메모리에 상주하며 다양한 상태를 갖는다. 프로세스가 활성화되어 종료되기까지의 살아있는 시간을 프로세스의 생명주기라고 한다.

프로세스의 생명주기는 다음과 같은 다섯단계로 나뉜다.

  1. new → 디스크에서 메모리로 프로그램이 올라가 실행준비를 하는 상태
  2. ready → 순서에 맞춰 처리를 기다리는 상태
  3. running → 작업이 처리되고 있는 상태
  4. waiting → 프로세스가 어떤 이벤트의 발생으로 기다리고 있는 상태
  5. terminated

CPU Scheduling

스케쥴러는 대기 큐에 있는 프로세스들을 특정한 우선순위를 기반으로 CPU를 할당받게 해준다. 다음 세가지 목적에 의해 스케쥴링을 수행한다.

  1. CPU의 활용 최대화
  2. 프로세스의 대기시간 최소화
  3. 처리량의 최대화

위의 세가지 목적을 수행하기 위해 스케쥴러는 다음의 스케쥴링 알고리즘 중 하나를 갖는다.

비선점 스케쥴링

이미 할당된 CPU를 다른 프로세스가 강제로 빼앗아 사용할 수 없는 스케쥴링 기법이다. 선점 방식보다 호출의 빈도가 낮고 문맥 교환에 의한 오버헤드도 적다. 따라서 일괄처리 시스템에 적합하다. 하지만 CPU사용시간이 긴 하나의 프로세스에 의해 다른 프로세스들을 오랜시간동안 대기시킬 수 있다.

  • Priority Scheduling → 미리 주어진 프로세스의 우선순위에 따라 처리한다.
  • FCFS: First Come First Serve → 먼저 도착한 프로세스를 먼저 처리한다.
  • SJF: Shortest Job First → 처리시간이 가장 짧은 프로세스 먼저 처리한다.
    • 평균 대기시간을 줄이기 위해 사용하는 방식이다. 실행시간이 긴 프로세스는 실행 시간이 짧은 프로세스에게 할당 순위가 밀려 연기 상태에 빠질 수 있다.
  • HRN: Highest Response-ratio Next → 우선순위 = (대기시간 + 서비스시간)/서비스시간과 같은 값을 우선순위로 두어 우선순위가 높은 것부터 실행한다.
    • 실행시간이 긴 프로세스에게 불리한 SJF방식을 보완한다.

선점 스케쥴링

하나의 프로세스가 CPU를 할당받고 실행하고 있는 와중에 우선순위가 높은 다른 프로세스가 CPU를 강제로 빼앗아 사용할 수 있는 기법이다. 비선점 방식보다 호출의 빈도가 높으며 문맥 교환에 의한 오버헤드가 크다. 빠른 응답시간을 요구하는 대화식 시분할 시스템에 적합하다.

  • RR: Round Robin → 프로세스마다 정해진 시간만큼 수행하고 작업이 끝난 프로세스는 대기 큐의 마지막에 가서 재할당을 기다린다.

  • Multilevel Queue → 대기 큐를 여러개로 나누어 큐마다 다른 스케쥴링 알고리즘을 갖는다.

    • 프로세스를 특정한 그룹들로 분리할 수 있는 경우 그룹에 따라 다른 큐와 알고리즘을 둔다.

    • 프로세스가 특정 그룹의 준비상태 큐에 들어갈 경우 다른 준비상태 큐로 이동할 수 없다.

    • 하위 준비상태 큐의 프로세스가 실행되는 중이더라도 상위 준비상태 큐에 프로세스가 새로 들어오면 CPU는 상위 프로세서에게 할당되어야 한다.

IPC(Inter Process Communication)

각 프로세스들은 별도의 공간에서 실행되기 때문에 한 프로세스에서 다른 프로세스의 메모리영역에 접근할 수 없다. 만약 프로세스가 다른 프로세스에 접근하려면 IPC를 사용해야 한다. IPC에는 크게 두가지 모델이 있는데 하나는 Message Passing모델이고 다른 하나는 Shared Memory모델이다.

전자의 방식이 Messagin Passing모델이고 후자의 방식이 Shared Memory모델이다.

Message Passing모델의 경우 메시지를 전달하기 위해 커널을 들린다. 이 과정에서 User Level과 Kernel Level을 넘나들게 되고 매번 system call이 호출되고 이에 따른 오버에드도 발생된다.

Shared Memory모델의 경우 프로세스 사이에 공유 공간이 존재하기 때문에 시스템 호출이 필요하지 않다. 이로 인해 커널 의존성도 낮고 속도도 빠르다. 하지만 공유 공간에 대한 제한이 존재한다.

스레드

프로세스 내에서 실행되는 흐름의 단위이다. 스레드는 운영체제의 스케쥴러에 의해 독립적으로 관리될 수 있는 프로그래밍 된 명령어의 가장 작은 시퀀스이다. 보통 하나의 프로그램은 하나 이상의 프로세스를 갖고 있으며 하나의 프로세스는 반드시 하나 이상의 스레드를 갖고 있다. 프로세스를 생성하면 기본적으로 하나의 메인스레드가 생성된다.

위 그림과 같이 프로세스는 실행될 때 운영체제로부터 각각 독립된 메모리 영역을 할당받는다. 스레드는 프로세스 내에서 스택 영역만 별도로 할당받고 부모 프로세스의 Code, Data, Heap영역은 공유한다. 따라서 프로세스 내의 자식 스레드들은 서로 주소공간이나 자원을 공유하면서 실행될 수 있다.

멀티프로세스

멀티프로세스에서 각 프로세스는 독립적으로 실행되며 각각 별도의 메모리 공간을 갖고 있다. 멀티프로세스는 하나의 프로그램을 여러개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 처리하도록 하는 것이다.

멀티프로세싱의 특징

  • 하나의 프로세스에 문제가 발생해도 다른 자식 프로세스에 영향이 확산되지 않는다. 안정성이 좋다.
  • 구현이 비교적 간단하다.
  • 프로세스 간 통신을 하기 위해 IPC를 통해야 하는데 이 경우 오버헤드가 발생한다.
  • 멀티스레드와 같이 별도의 동기화 작업이 필요하지 않다.
  • 프로세스마다 각각 독립된 메모리 공간을 할당해야 하므로 불필요한 메모리 사용량이 많다.
  • 스케쥴링에 따른 문맥교환이 많아지고 성능 저하의 우려가 있다.

멀티스레드

하나의 어플리케이션을 여러개의 스레드로 구성하여 하나의 스레드가 하나의 작업을 처리하도록 하는 것이다. 만약 단일 스레드로 네트워크나 데이터베이스 통신과 같은 긴 작업을 수행하는 경우 다른 작업을 처리할 수 없기 때문에 여러개의 스레드를 사용한다.

멀티스레드의 특징

  • 응답성이 좋다. 자식 스레드 중 하나가 오류 또는 긴 작업으로 중단되어도 프로그램이 계속적을 동작된다.
  • 스레드들은 부모 프로세스의 자원과 메모리를 공유할 수 있기에 스레드 간 자원 공유가 쉽다.
  • 새로운 프로세스를 할당하는 것보다 새로운 스레드를 할당하는 것이 더 비용이 적다.
  • 구현, 테스트, 디버깅이 어렵다.
  • 스레드 간 별도의 동기화 작업이 필요하며 교착상태가 발생하지 않도록 주의해야 한다.
  • 자식 스레드 중 하나에 문제가 생기면 전체 프로세스에 영향을 미칠 수 있다.

멀티스레드의 동기화(임계영역 문제)

스레드들은 부모 프로세스의 메모리 공간을 공유하는데 여러 스레드가 동일한 메모리 공간을 접근하면서 동기화 문제가 발생한다.

스레드들 간에 한 번에 하나의 스레드만 공유자원에 접근하게 함으로써 동기화(임계영역) 문제를 해결할 수 있다.

임계영역 문제를 해결하기 위한 조건

  1. 상호배제(Mutual Exclusion)
    • 어떤 프로세스가 임계영역에서 실행중이라면 다른 프로세스들은 동일한 임계영역에서 실행될 수 없다.
  2. 진행(Progress)
    • 임계영역에서 실행중인 프로세스가 없고 들어가야 하는 프로세스가 여러개 있다면 어느 것이 들어갈지 적절히 선택해주어야 한다.
  3. 한정된 대기(Bounded Waiting)
    • 다른 프로세스의 기아를 방지하기 위해 한 번 임계 구역에 들어간 프로세스는 다음 임계구역에 들어갈 때 제한을 두어야 한다.

임계영역 문제의 해결책

  1. Lock
    • 하나의 스레드나 프로세스가 자원을 사용하고 있는 동안에는 잠궈서 다른 프로세스나 스레드가 접근을 못하게 하는 방식이다.
    • 하드웨어 기반의 해결책으로 임계영역에 접근하는 프로세스는 Lock을 획득하고 임계영역에서 빠져나오면서 Lock을 방출하는 방법으로 임계영역에 동시에 접근할 수 없게 한다.
  2. Semaphore
    • 소프트웨어상에서 임계영역 문제를 해결하기 위한 동기화 도구
    • Counting Semaphore
      • 공유자원의 개수를 나타낸다.
      • 자원을 사용하면 세마포어가 감소하고 임계구역에서 빠져나오면 세마포어가 증가한다.
    • Binary Semaphore(Mutex)
      • 0과 1사이의 값만 가능한 세마포어이다.
  3. Monitor
    • 그 사용이 세마포어와 유사하지만 세마포어가 운영체제 단계에서 사용되는 반면 모니터는 프로그래밍 언어 수준에서 사용된다.
    • 락의 설정, 해제를 알아서 처리해준다.

멀티스레드와 멀티프로세스의 비교

자원의 효율성 측면

멀티스레드는 프로세스 내 자원을 공유하기 때문에 멀티프로세스에 비해 시스템 자원 소모가 줄어든다.

응답시간과 처리비용 측면

프로세스간 IPC를 사용하는 것은 비용이 크다. 스레드의 경우 공유자원의 이용을 통해 스레드간 통신의 비용이 적다. 또한 프로세스 간 문맥교환은 스레드 간 문맥교환보다 느리다. 그 이유로 스레드는 문맥 교환 과정에서 Stack영역만 처리하면 되기 때문이다.

안정성 측면

멀티스레드가 동일한 공간을 공유하면서 생기는 임계영역 문제가 있다. 멀티프로세스의 경우 프로그램의 문제가 생기면 프로그램을 중단시키고 다시 시작하면 되지만 멀티스레드 방식의 경우에는 하나의 스레드가 공유공간을 망가뜨리면 해당 공간을 공유하는 모든 스레드를 망가뜨릴 수 있다.

참고자료

프로세스 - 위키백과, 우리 모두의 백과사전

스레드 (컴퓨팅) - 위키백과, 우리 모두의 백과사전

Process와 Thread 이야기

PCB(Process Control Block)란?

운영체제 프로세스 생애주기(Process Lifecycle)에 대해서

[병렬프로그래밍] 멀티 스레드와 동기화

[OS] - 임계 영역(Critical Section)과 해결방안(Lock / Semaphore / Monitor)

0개의 댓글