Post

[혼자 공부하는 컴퓨터구조+운영체제]10장 프로세스와 스레드

10-1 프로세스 개요

프로세스 직접 확인하기

  • 포그라운드 프로세스(foreground process): 사용자가 보는 앞에서 실행되는 프로세스
  • 백그라운드 프로세스: 사용자가 보지 못하는 뒤에서 실행되는 프로세스
    • 유닉스의 데몬(daemon) 또는 윈도우의 서비스:사용자와 상호작용하지 않는 백그라운드 프로세스

프로세스 제어 블록

  • 프로세스는 타이머 인터럽트가 발생 시 CPU 사용을 넘기고 다음 차례를 기다림
    • 타이머 인터럽트(타임아웃 인터럽트): 클럭 신호를 발생시키는 장치에서 발생하는 하드웨어 인터럽트
  • 프로세스 제어 블록(Process Control Block, PCB)
    • 프로세스와 관련된 정보를 저장하는 자료 구조
    • 프로세스 실행 순서와 자원 배분을 관리할 때 사용
    • 커널 영역에 생성
    • 프로세스 생성 시 만들어지고 실행이 끝나면 폐기
      • “프로세스가 생성됐다.” ⇒ “운영체제가 PCB를 생성했다.”
      • “프로세스가 종료됐다.” ⇒ “운영체제가 PCB를 폐기했다.”

PCB에 담기는 대표적인 정보

  • 프로세스 ID(PID)
    • 프로세스 식별을 위해 부여된 고유 번호
  • 레지스터값
    • 해당 프로세스가 실행하며 사용했던, 프로그램 카운터를 비롯한 레지스터 값
    • 자신의 실행 차례가 돌아오면 이를 통해 사용했던 레지스터 값을 복원
  • 프로세스 상태
    • CPU를 사용하기 위해 기다리는지, CPU를 사용하고 있는 상태인지 등
  • CPU 스케줄링 정보
    • 언제 어떤 순서로 프로세스가 CPU를 할당받을지에 대한 정보
  • 메모리 관련 정보
    • 프로세스가 어느 주소에 저장되어 있는지에 대한 정보
    • 베이스 레지스터, 한계 레지스터
    • 페이지 테이블 정보
  • 사용한 파일과 입출력장치 목록
    • 어떤 입출력장치가 프로세스에 할당되었는지, 어떤 파일을 열었는지에 대한 정보

문맥 교환

  • 문맥: 하나의 프로세스 수행을 재개하기 위해 기억해야 할 정보
    • 해당 프로세스의 PCB에 표현 ⇒ 문맥은 PCB에 기록되는 정보
  • 문맥 교환: 기존 프로세스의 문맥을 PCB에 저장하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB로부터 복구하여 새로운 프로세스를 실행하는 것
    • 여러 프로세스가 빠르게 번갈아 가며 실행되는 원리
    • 너무 자주 문맥 교환을 하면 오버헤드 발생 가능

프로세스의 메모리 영역

프로세스가 생성되면 커널 영역에 생기는 PCB 외에도, 프로세스가 사용자 영역에 코드 영역, 데이터 영역, 힙 영역, 스택 영역으로 나누어 저장된다.

  • 코드 영역(code segment, 텍스트 영역)
    • 실행할 수 있는 기계어로 이루어진 명령어 저장
    • CPU가 실행할 명령어가 담겨있기 때문에 쓰기 금지 ⇒ 읽기 전용 공간
    • 크기가 고정된 영역 ⇒ 정적 할당 영역
  • 데이터 영역(data segment)
    • 프로그램이 실행되는 동안 유지할 데이터 저장
      • 예) 전역 변수
    • 크기가 고정된 영역 ⇒ 정적 할당 영역
  • 힙 영역(heap segment)
    • 프로그래머가 직접 할당할 수 있는 저장 공간
    • 힙 영역에 메모리 공간을 할당하면 언젠가는 반환해야 함
      • 반환하지 않는다면 메모리를 낭비하게 됨 ⇒ 메모리 누수(memory leak)
    • 프로세스 실행 과정에서 크기 변경 가능 ⇒ 동적 할당 영역
    • 메모리의 낮은 주소에서 높은 주소로 할당
  • 스택 영역(stack segment)
    • 데이터를 일시적으로 저장하는 곳
      • 예) 매개 변수, 지역 변수
    • 프로세스 실행 과정에서 크기 변경 가능 ⇒ 동적 할당 영역
    • 메모리의 높은 주소에서 낮은 주소로 할당

10-2 프로세스 상태와 계층 구조

프로세스 상태

  • 생성 상태(new)
    • 프로세스를 생성 중인 상태
    • 이제 막 메모리에 적재되어 PCB를 할당받은 상태
    • 이후 준비 상태가 되어 CPU의 할당을 기다림
  • 준비 상태(ready)
    • CPU를 할당받아 실행될 수 있지만 차례가 오지 않아 기다리는 상태
    • 디스패치: 준비 상태에서 실행 상태로의 전환
  • 실행 상태(running)
    • CPU를 할당받아 실행 중인 상태
    • 할당된 일정 시간 동안만 CPU 사용 가능
    • 타이머 인터럽트가 발생하면 준비 상태로 전환
    • 입출력장치의 작업을 기다려야 한다면 대기 상태로 전환
  • 대기 상태(blocked)
    • 입출력장치가 입출력을 끝내 입출력 완료 인터럽트를 보낼 때까지 기다리는 상태
      • 입출력 작업은 CPU에 비해 속도가 느리기 때문
    • 입출력 작업이 완료되면 준비 상태로 전환
    • 입출력 작업 외에 다른 특정 이벤트를 기다릴 수도 있음
  • 종료 상태(terminated)
    • 프로세스가 종료되어 운영체제가 PCB와 메모리를 정리한 상태

프로세스 계층 구조

  • 부모 프로세스: 시스템 호출을 통해 새 프로세스를 생성한 프로세스
  • 자식 프로세스: 생성된 프로세스
  • 부모 프로세스와 자식 프로세스는 서로 다른 프로세스 ⇒ 각기 다른 PID 소유
    • 일부 운영체제는 자식 프로세스의 PCB에 PPID(Parent PID) 기록
  • 컴퓨터 부팅 → 최초의 프로세스 실행 → 자식 프로세스 생성 → 자식 프로세스 생성 → …
    • 이러한 과정으로 생긴 트리 구조를 프로세스 계층 구조라 한다.
    • 데몬이나 서비스 또한 최초 프로세스의 자식 프로세스다.
  • 최초의 프로세스
    • 유닉스의 init, 리눅스의 systemd, macOS의 launchd
    • PID는 항상 1번

프로세스 생성 기법

  • fork
    • 프로세스 자신의 복사본을 만드는 시스템 호출
      • 부모 프로세스가 자신의 복사본을 자식 프로세스로 생성
    • 부모 프로세스의 자원이 자식 프로세스에 상속됨
  • exec
    • 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰는 시스템 호출
      • 자식 프로세스가 자신의 메모리 공간을 다른 프로그램으로 교체
    • 코드 영역과 데이터 영역의 내용이 실행할 프로그램의 내용으로 바뀌고 나머지 영역은 초기화
  • fork와 exec를 반복하며 여러 프로세스가 계층적으로 실행된다.
  • fork 뒤에 부모 프로세스와 자식 프로세스 누구도 exec를 호출하지 않는 경우,
    부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 된다.

10-3 스레드

프로세스와 스레드

  • 스레드: 프로세스를 구성하는 실행 단위
  • 프로세스 내에서 스레드마다 각기 다른 코드 실행 가능
    • 스레드는 각기 다른 프로그램 카운터값을 비롯한 레지스터 값, 스택으로 구성되기 때문
  • 스레드는 실행에 필요한 최소한의 정보만을 유지한 채 프로세스의 자원을 공유
    • 최소한의 정보 ⇒ 프로그램 카운터를 포함한 레지스터, 스택
  • 리눅스 운영체제에선 프로세스와 스레드를 구분하지 않고 태스크로 통일

멀티프로세스와 멀티스레드

  • 멀티프로세스: 여러 프로세스를 동시에 실행하는 것
  • 멀티스레드: 여러 스레드로 프로세스를 동시에 실행하는 것

멀티프로세스와 멀티 스레드의 차이

  • 멀티프로세스
    • 프로세스를 fork하여 여러 프로세스를 동시에 실행 → 모든 자원이 복제되어 메모리에 적재
      ⇒ 메모리에 동일한 내용이 중복하여 존재 ⇒ 메모리 낭비
    • 하나의 프로세스에 문제가 생겨도 다른 프로세스에 지장이 적거나 없음
  • 멀티스레드
    • 같은 프로세스 내의 모든 스레드는 코드, 데이터, 힙 영역과 프로세스 자원(열린 파일 등)을 공유
      ⇒ 메모리를 효율적으로 사용
    • 같은 자원을 공유하기 때문에 통신에 유리
    • 하나의 스레드에 문제가 생기면 프로세스 전체에 지장을 초래

프로세스 간 통신

  • Inter-Process Communication(IPC)
  • 기본적으로 프로세스 간 자원은 공유되지 않지만, 불가능한 건 아니다.
  • 통신(데이터를 주고받는) 방법
    1. 파일을 통한 프로세스 간 통신
    2. 공유 메모리(shared memory)를 두어 데이터를 주고받는 통신
    3. 소켓, 파이프를 이용한 통신
This post is licensed under CC BY 4.0 by the author.