7 분 소요

본 글은 (KOCW) 운영체제, 이화여자대학교 반효경 교수님의 강의를 듣고 내용을 요약 및 정리했습니다. 개인 공부에 목적이 있으며, 자세한 사항은 http://www.kocw.or.kr/home/cview.do?mty=p&kemId=1046323에 참고하시면 됩니다.

Chapter 3.

  • Process1 - 1시간
  • Process2 - 15분
  • Process3 - 15분

Chapter 4.

  • Process Management 1 - 11분
  • Process Management 2 - 1시간 7분

(+) 인프런의 주니온 박사님의 운영체제 공룡책 강의를 듣고 내용을 보충했습니다. 자세한 사항은 여기를 참고하시면 됩니다.

image image

운영체제에서 프로세스는 실행 중인 프로그램의 인스턴스이자 CPU 스케줄링의 기본 단위이다. 이 글은 프로세스의 상태와 PCB, 문맥 교환, 스케줄러와 큐, 스레드, 그리고 fork·exec·wait·exit 시스템 콜과 프로세스 간 협력(IPC)을 정리한다. 프로세스가 무엇인지에서 출발해 상태와 관리, 스레드, 생성과 협력의 흐름을 따라가면 운영체제의 프로세스 관리가 한눈에 잡힌다.

이 글에서 다루는 것

  • 프로세스의 정의와 문맥(context) 구성 살펴보기
  • 프로세스 상태 변화와 PCB·문맥 교환 이해하기
  • 스케줄러의 종류와 큐의 역할 구분하기
  • 스레드의 개념과 구현, 프로세스와의 차이 정리하기
  • fork·exec·wait·exit 시스템 콜과 프로세스 간 협력(IPC) 다루기

프로세스

프로세스는 실행 중인 프로그램의 인스턴스이며, 운영체제는 상태·PCB·큐를 통해 이를 관리한다. 그 개념과 관리 방식부터 정리한다.

  • “Process is an instance of a program in execution”
    • 하나의 프로그램은 몇몇 프로세스들이 될 수 있다.
    • 프로세스는 process ID(PID)를 통해 식별된다.
    • 프로세스는 CPU context (registers), OS resources, other information을 포함한다.
  • 프로세스의 문맥(context)
    • CPU 수행 상태를 나타내는 하드웨어 문맥(context)
      • Program Counter
      • 각종 register (주로 register가 어떤 값인지 본다)
    • 프로세스의 주소 공간
      • code, data, stack
      • 함수 호출이 어떻게 쌓여 있고 data가 어떤 상태인지 등 프로세스의 상태
    • 프로세스 관련 커널 자료 구조
      • PCB (Process Control Block)
        • 각 프로세스는 PCB에 의해 운영체제에 표시된다.
        • PCB는 특정 프로세스와 관련된 많은 정보들을 가지고 있다.
        • ex. 이 프로세스에게 얼마나 할당해야 하는지
      • Kernel stack
        • 커널도 함수로 이루어져 있다.
        • 커널은 여러 프로세스들이 공유하는 코드라 할 수 있다.
        • 커널 스택은 프로세스마다 별도로 있다.

프로세스의 상태 (Process State)

  • 프로세스는 상태(state)가 변경되며 수행된다.
    • Running : CPU를 잡고 instruction을 수행 중인 상태
    • Ready : CPU를 기다리는 상태 (메모리 등 다른 조건을 모두 만족하고)
    • Blocked (wait, sleep) : CPU를 주어도 당장 instruction을 수행할 수 없는 상태
      • Process 자신이 요청한 event(예: I/O)가 즉시 만족되지 않아 이를 기다리는 상태
        • ex. 디스크에서 file을 읽어와야 하는 경우
  • New : 프로세스가 생성 중인 상태
  • Terminated : 수행(execution)이 끝난 상태

스레드(프로세스)의 상태 전이 — Running에서 wait 함수 호출로 Waiting, 이벤트가 충족되면 Ready를 거쳐 다시 Running으로 돌아온다

출처: CPU Analysis — Thread State Transitions, Microsoft Learn (https://learn.microsoft.com/en-us/windows-hardware/test/wpt/cpu-analysis), CC BY 4.0

PCB (Process Control Block)

  • Process Control Block의 약어.
    • 블록 (block) : 작은 단위들이 합쳐져 일정 구획을 갖는 집합체 1
  • PCB : 운영체제가 각 프로세스를 관리하기 위해 프로세스당 유지하는 정보
  • 다음의 구성 요소를 가진다. (구조체로 유지)
    • (1) OS가 관리상 사용하는 정보
      • Process state, Process ID(PID)
      • scheduling information, priority
    • (2) CPU 수행 관련 하드웨어 값
      • Program counter, Registers
    • (3) 메모리 관련
      • Code, Data, Stack의 위치 정보
    • (4) 파일 관련
      • Open file descriptors

문맥 교환 (Context Switch)

  • 문맥 교환 (Context Switch) : CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 과정
    • 프로세스의 context는 PCB에 있다
  • CPU가 다른 프로세스에게 넘어갈 때 운영체제는 다음을 수행
    • CPU를 내어주는 프로세스의 상태를 그 프로세스의 PCB에 저장
    • CPU를 새롭게 얻는 프로세스의 상태를 PCB에서 읽어옴

핵심은 저장과 복원이다.

문맥 교환은 비용이 큰 작업이라, 운영체제는 한 실행 단위(스레드)에 quantum(할당 시간)을 부여한 뒤 다음 실행 단위로 전환해 오버헤드를 줄인다.2

프로세스를 스케줄링하기 위한 큐

  • Job queue : 현재 시스템 내에 있는 모든 프로세스의 집합
  • Ready queue : 현재 메모리 내에 있으면서 CPU를 잡아서 실행되기를 기다리는 프로세스의 집합
  • Device queues : I/O device의 처리를 기다리는 프로세스의 집합
  • 프로세스들은 각 큐들을 오가며 수행된다.

스케줄러 (Scheduler)

  • Long-term scheduler (Job scheduler)
    • 시작 프로세스(new 상태의 프로세스)가 메모리에 올라오는 것을 관리
    • 시작 프로세스 중 어떤 것들을 ready queue로 보낼지 결정
    • degree of multi-programming을 제어
    • multi-programming: 2개 이상의 프로그램을 주기억장치에 기억시키고, 중앙처리장치를 번갈아 사용하는 처리기법
    • time sharing system에는 보통 장기 스케줄러가 없음 (무조건 ready)
      • time sharing의 목적은 프로세스 간에 CPU를 자주 번갈아 할당해, 사용자가 프로그램이 동작하는 동안 상호작용(interact)할 수 있게 하는 것이다.
  • Short-term scheduler (CPU scheduler)
    • 어떤 프로세스를 다음번에 running시킬지 결정
    • 짧은 시간 안에 스케줄이 이루어져야 함
    • 충분히 빨라야 함(millisecond 단위)
  • Medium-term scheduler (Swapper)
    • 여유 공간 마련을 위해 프로세스를 통째로 메모리에서 디스크로 쫓아냄
    • 프로세스에게서 memory를 빼앗는 문제
    • degree of multi-programming을 제어

프로세스의 상태

  • Running
  • Ready
  • Blocked
  • Suspended (stopped)
    • 외부적인 이유로 프로세스의 수행이 정지된 상태
    • 프로세스는 통째로 디스크에 swap out 됨
    • ex. 사용자가 프로그램을 일시 정지시킨 경우 (break key)
  • Blocked : 자신이 요청한 event가 만족되면 Ready
  • Suspended : 외부에서 resume 해주어야 Active

주의: Blocked는 기다리던 event가 만족되면 스스로 Ready로 가지만, Suspended는 외부에서 resume해 주어야 Active로 돌아온다.

프로세스 단위의 상태와 관리 방식을 살펴봤으니, 이제 프로세스 내부의 더 작은 실행 단위인 스레드로 넘어간다.

Thread

스레드는 프로세스 내부에서 CPU를 수행하는 가벼운 실행 단위로, 자원을 공유해 동시성을 저렴하게 얻는 방법이다.

  • 스레드는 “프로세스 안에서 동시성을 더 저렴하게 늘릴 수 없을까”라는 의문에서 출발한다.
    • 실행 상태에서 프로세스를 분리한다.
  • 스레드 (thread) : 프로세스 내부의 실행 단위
    • A thread is a lightweight process.
  • 프로세스 하나에 CPU 수행 단위(a basic unit of CPU utilization)만 여러 개 두고 있다.
  • 프로세스 하나에서 공유할 수 있는 것은 공유하고 CPU 수행에 관한 정보(CPU 카운터, register set, stack etc.)는 별도로 가지고 있다.
  • Thread의 구성 : Program counter, register set, Stack space
  • Thread가 동료 Thread와 공유하는 부분(= Task) : code section, data section, OS resources

  • single-threaded process vs multithreaded process

  • web server에서의 multithreading 예시

Thread의 장점

  • Responsiveness (응답성)
    • eg) multi-threaded Web
      • if one thread is blocked (eg network), another thread continues (eg display)
  • Resource Sharing (자원 공유)
    • 여러 개의 스레드가 프로세스 내부의 자원들을 공유할 수 있다
  • Economy (경제성)
    • 스레드 생성과 스레드 간 문맥 교환은 프로세스 생성과 프로세스 간 문맥 교환보다 저렴하다.
      • overhead(어떤 처리를 하기 위해 들어가는 간접적인 처리 시간, 메모리)를 줄일 수 있다.
  • Utilization of MP(Multi-Processor) Architectures
    • 서로 다른 CPU에서 각 스레드들이 병렬적으로 일을 처리하면 결과를 빨리 얻을 수 있다.

Thread 구현

  • Kernel Threads : 프로세스 안에 스레드가 여러 개 있다는 걸 운영체제가 알고 있음
    • 커널이 알아서 스레드 관리
  • User Threads : 프로세스 안에 스레드가 여러 개 있다는 걸 운영체제는 모름
    • 유저 프로그램이 스레드를 직접 관리
    • 구현상의 제약이 있을 수 있다.

Process vs Thread

  • 프로세스는 여러 개의 스레드를 가질 수 있다.
  • 스레드는 단일 프로세스에 묶인다(bound).
  • 프로세스는 스레드가 실행되는 컨테이너이다.
    • PID, 주소 공간, 사용자 및 그룹 ID, 열린 파일 설명자, 현재 작업 디렉토리 등
  • 스레드 간 데이터 공유 비용이 저렴하다.
    • 모두 동일한 주소 공간을 본다.
  • 스레드는 스케줄링 단위이다.
  • 프로세스는 정적(static)인 반면 스레드는 동적(dynamic) 엔티티이다.

차이는 자원을 공유하느냐에서 갈린다.

one-to-one

  • 각 사용자 수준 스레드는 커널 스레드에 매핑된다.
  • 사용자 수준 스레드를 만들면 커널 스레드가 생성된다.
  • 다대일(many to one)보다 동시성 향상이 특징이다.
  • 리눅스는 NPTL(Native POSIX Threads Library)에서 이 1:1 모델을 사용하며, 한 프로세스의 모든 스레드는 같은 PID를 공유하는 스레드 그룹(thread group)으로 커널에 표현된다.3
  • 오버헤드로 인해 프로세스당 스레드 수가 제한되는 경우가 있다.

many-to-one

  • 단일 커널 스레드에 매핑된 많은 사용자 수준 스레드를 말한다.
  • 사용자 스레드 간의 작고 빠른 컨텍스트 전환이 이뤄진다.
  • 하나의 스레드 차단이 되면, 모든 스레드가 차단된다.
  • 한 번에 하나의 스레드만 커널에 있을 수 있기 때문에 다중 스레드는 다중 코어 시스템에서 병렬로 실행되지 않을 수 있다.
  • 현재 이 모델을 사용하는 시스템이 거의 없다.

many-to-many

  • 많은 사용자 수준 스레드를 여러 커널 스레드에 다중화
  • 운영체제에서 충분한 수의 커널 스레드를 생성할 수 있다.

스레드가 프로세스 내부의 실행 단위라면, 다음은 프로세스 자체를 생성하고 종료하는 시스템 콜이다.

프로세스 생성 (Process Creation)

프로세스는 fork로 복제되고 exec로 새 프로그램을 올리며, wait와 exit로 생을 마친다. 그리고 필요하면 프로세스끼리 협력한다.

  • Copy-on-Write (COW) : write가 발생했을 때 Copy해서 쓴다.
  • 부모 프로세스(Parent process)가 자식 프로세스(children process) 생성
  • 프로세스의 트리(계층 구조) 형성
  • 프로세스는 자원을 필요로 함
    • 운영체제로부터 받는다.
    • 부모와 공유한다.
  • 자원의 공유
    • 부모와 자식이 모든 자원을 공유하는 모델
    • 일부를 공유하는 모델
    • 전혀 공유하지 않는 모델
  • 수행 (Execution)
    • 부모와 자식은 공존하며 수행되는 모델
    • 자식이 종료(terminate)될 때까지 부모가 기다리는(wait) 모델
  • 주소 공간 (Address space)
    • 자식은 부모의 공간을 복사함 (binary and OS data)
    • 자식은 그 공간에 새로운 프로그램을 올림
  • 유닉스의 예
    • fork() 시스템 콜이 새로운 프로세스를 생성
      • 부모를 그대로 복사 (OS data except PID + binary)
      • 주소 공간 할당
    • fork 다음에 이어지는 exec() 시스템 콜을 통해 새로운 프로그램을 메모리에 올림
  • 프로세스가 마지막 명령을 수행한 후 운영체제에게 이를 알려줌 (exit)
    • 자식이 부모에게 output data를 보냄 (via wait)
    • 프로세스의 각종 자원들이 운영체제에게 반납됨
  • 부모 프로세스가 자식의 수행을 종료시킴 (abort)
    • 자식이 할당 자원의 한계치를 넘어섬
    • 자식에게 할당된 태스크가 더 이상 필요하지 않음
    • 부모가 종료(exit)하는 경우
      • 운영체제는 부모 프로세스가 종료하는 경우 자식이 더 이상 수행되도록 두지 않는다.
      • 단계적인 종료

fork() 시스템 콜

  • fork() : create a child (copy)
  • 프로세스는 fork() 시스템 콜에 의해 생성된다.

exec() 시스템 콜

  • exec() : overlay new image
  • 프로세스는 exec() 시스템 콜을 통해 다른 프로그램을 실행한다.
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("1");
    execlp("echo", "echo", "hello", "3", (char *)0);
    printf("2");
    return 0;
}

wait() 시스템 콜

  • wait() : sleep until child is done
  • 프로세스 A가 wait() 시스템 콜을 호출하면
    • 커널은 child가 종료될 때까지 프로세스 A를 sleep시킨다. (block 상태)
    • Child process가 종료되면 커널은 프로세스 A를 깨운다. (ready 상태)

정리하면, wait는 자식이 끝날 때까지 부모를 block 상태로 재우고, 자식이 종료되면 ready 상태로 깨우는 절차다.

exit() 시스템 콜

  • exit() : frees all the resources, notify parent
  • 프로세스의 종료
    • 자발적 종료
      • 마지막 statement 수행 후 exit() 시스템 콜을 통해
      • 프로그램에 명시적으로 적어주지 않아도 main 함수가 리턴되는 위치에 컴파일러가 넣어줌
    • 비자발적 종료
      • 부모 프로세스가 자식 프로세스를 강제 종료시킴
        • 자식 프로세스가 한계치를 넘어서는 자원 요청
        • 자식에게 할당된 태스크가 더 이상 필요하지 않음
      • 키보드로 kill, break 등을 친 경우
      • 부모가 종료하는 경우
        • 부모 프로세스가 종료하기 전에 자식들이 먼저 종료됨

정리하면, 프로세스는 스스로 exit를 호출해 자발적으로 끝나거나, 부모가 abort를 호출해 강제로 종료된다.

프로세스 간 협력

  • 독립적 프로세스 (Independent process) : 프로세스는 각자의 주소 공간을 가지고 수행되므로 원칙적으로 하나의 프로세스는 다른 프로세스의 수행에 영향을 미치지 못함
  • 협력 프로세스 (Cooperating process) : 프로세스 협력 메커니즘을 통해 하나의 프로세스가 다른 프로세스의 수행에 영향을 미칠 수 있음
  • 프로세스 간 협력 메커니즘 (IPC; Inter-Process Communication) : send data to and receive data from each other.
    • 메시지를 전달하는 방법
      • message passing : 커널을 통해 메시지 전달
    • 주소 공간을 공유하는 방법
      • shared memory : 서로 다른 프로세스 간에도 일부 주소 공간을 공유하게 하는 shared memory 메커니즘이 있음
      • thread : 스레드는 사실상 하나의 프로세스이므로 프로세스 간 협력으로 보기는 어렵지만 동일한 프로세스를 구성하는 스레드들 간에는 주소 공간을 공유하므로 협력이 가능

결국 메시지냐 공유 메모리냐의 선택이다.

Shared memory

  • Producer-Consumer 문제
    • producer는 consumer에 의해 소비되는 정보를 만들어 낸다.
  • shared-memory를 사용하여 해결
    • producer와 consumer에게 concurrent하게 동작하도록 허용한다.
    • buffer가 있다면, producer는 buffer를 채우고 consumer는 buffer를 비운다.
  • shared-memory는 producer와 consumer 프로세스에 의해 공유되는 메모리의 영역이다.

Message Passing

  • Message system : 프로세스 사이에 공유 변수(shared variable)를 일체 사용하지 않고 통신하는 시스템
    • send(message)
    • receive(message)
  • Direct Communication : 통신하려는 프로세스의 이름을 명시적으로 표시
    • send(P, message)
    • receive(Q, message)
    • 링크는 자동으로 생성되고, 통신하는 프로세스 쌍마다 하나만 존재한다.

  • Indirect Communication : mailbox (또는 port)를 통해 메시지를 간접 전달
    • send(A, message)
    • receive(A, message)
    • 하나의 링크가 2개 이상의 프로세스와 연관될 수 있다.
  • 메시지 전달 시스템을 위한 다른 설계 옵션
    • blocking or non-blocking : synchronous or asynchronous
    • Blocking send : the sender is blocked until the message is received.
    • Non-blocking send : the sender sends the message and continues.
    • Blocking receive : the receiver blocks until a message is available.
    • Non-blocking receive : the receiver retrieves either a valid message or a null message.

프로세스 관리 기법은 저마다 비용을 안고 있다. 문맥 교환은 CPU를 넘길 때마다 PCB를 저장·복원하는 오버헤드를 만들므로 잦아질수록 성능이 떨어진다. 스레드는 자원을 공유해 생성·전환 비용을 줄이지만, 여러 스레드가 같은 주소 공간을 쓰므로 동기화 없이는 데이터가 깨질 수 있고 한 스레드의 오류가 프로세스 전체를 종료시킬 수 있다. 협력 방식도 마찬가지여서, shared memory는 데이터 복사 없이 빠른 대신 동기화 부담을 프로그래머에게 넘기고, message passing은 그 부담을 커널이 지는 대신 시스템 콜과 데이터 복사 오버헤드가 따른다. 결국 어느 기법이든 비용을 어디에 두느냐의 선택이다.

핵심 정리

  • 프로세스 = 실행 중인 프로그램. 상태·PCB·큐로 관리되며, 문맥 교환은 CPU를 넘길 때 PCB에 상태를 저장하고 복원하는 과정이다.
  • 스케줄러가 순서를 정한다. 장기·단기·중기 스케줄러가 degree of multi-programming과 CPU 배분을 조정한다.
  • 스레드는 가벼운 실행 단위. code·data·OS 자원은 공유하고 PC·register·stack만 따로 가진다.
  • fork·exec·wait·exit. 생성·덮어쓰기·대기·종료의 시스템 콜 흐름으로 프로세스가 태어나고 끝난다.
  • 협력은 두 갈래. message passing과 shared memory로 프로세스가 데이터를 주고받는다.

References

댓글남기기