os computer_science cs 운영체제 OS 프로세스 스레드

[CS/Computer Science][운영체제 / OS] 프로세스와 스레드

Kwangjin Park

May 11, 2025 · 8 min read

Follow

이번 포스트에서는 프로세스와 스레드에 대해 자세히 알아보겠습니다.

1. 개요

프로세스의 유형

  • 포그라운드 프로세스(foreground process): 사용자가 보는 공간에서 사용자와 상호작용하며 실행
  • 백그라운드 프로세스(background process): 사용자가 보지 못하는 곳에서 실행
    • 데몬: 백그라운드 프로세스 중, 사용자와 별다른 상호작용 없이 주어진 작업만 수행
    • 서비스: 데몬을 윈도우 운영체제에서 부르는 말

프로세스 정보가 저장되는 영역

  • 커널영역
    • 프로세스 제어 블록(PCB)에 저장
  • 사용자 영역
    • 코드 영역, 데이터 영역, 힙 영역, 스택 영역으로 나뉘어 저장 image1
    • 정적 영역: 프로그램 실행 도중 크기가 변하지 않음
      1. 코드 영역(code segment, 텍스트 영역)
        • 실행 가능한 명령어가 저장되는 공간
        • CPU가 읽고 실행할 명령어가 담겨 있음 → “Read Only” 공간
      2. 데이터 영역(data segment)
        • 프로그램이 실행되는 동안 유지할 데이터가 저장되는 공간
        • 정적 변수, 전역 변수 등
        • 추가 구분: BSS 영역 - 초기화 여부의 차이
          • 초깃값이 있는 데이터: 데이터 영역에 저장
          • 초깃값이 없는 데이터: BSS 영역에 저장

    • 동적 영역: 프로그램 실행 도중 크기가 변할 수 있는 영역
      1. 힙 영역(heap segment)
        • 개발자가 직접 할당 가능한 저장공간 → 프로그램 실행 중 비교적 자유롭게 할당 가능
        • 힙 영역에 메모리를 할당하였다면, 언젠가는 할당 공간을 반환해야 함
          • 반환하지 않는다면 메모리 누수(memory leak) 문제 발생: 할당한 공간이 계속 남아 메모리 낭비
          • 가비지 컬렉션: 메모리 누수 문제 해결을 위해 프로그래밍 언어 자체에서 사용되지 않는 힙 메모리를 해제하는 기능
      2. 스택 영역(stack segment)
        • 일시적으로 사용할 값들이 저장되는 공간
          • 매개변수, 지역변수, 함수 복귀 주소 등이 저장
        • 스택 트레이스 형태의 함수 호출 정보가 저장됨
          • 스택 트레이스(stack trace): 특정 시점에 저장된 함수 호출 정보 → 문제 발생 지점을 추적하는 데 매우 유용(디버깅에 활용)

PCB와 문맥 교환

  • PCB(문맥 제어 블록, Process Control Block): 프로세스를 식별할 수 있는 커널 영역 내의 정보
    • OS가 메모리에 적재된 다수의 프로세스를 관리하기 위한 정보
    • 프로세스에 관한 다양한 정보를 내포하는 구조체의 일종
      • 구조체(struct): 서로 다른 자료형으로 이루어진 데이터를 하나로 묶어 활용할 수 있도록 하는 복잡 자료형의 일종.
  • PCB의 생성 및 폐기
    • 생성: 새로운 프로세스가 메모리에 적재 시(=프로세스 생성)
    • 폐기: 프로세스 실행 종료시
  • PCB가 담고 있는 내용
    1. PID(Process ID)
    2. (프로세스의 실행 과정에서 사용한)레지스터 값
    3. 프로세스 (현재)상태
    4. CPU 스케줄링(우선순위)
      • 프로세스의 CPU 할당 순서
    5. 메모리 관련 정보
      • 메모리 상 프로세스의 적재위치
    6. 파일 및 입출력 장치 관련 정보

      • PCD example - task struct(Linux 운영체제의 PCB) image2
  • 프로세스 테이블
    • 실행중인 PCB의 모음
    • 다수의 PCB는 커널 내 프로세스 테이블의 형태로 관리되는 경우가 많음
    • PCB 추가 및 제거
      • 추가: 새롭게 실행되는 프로세스는 해당 프로세스의 PCB를 프로세스 테이블에 추가 / 필요 자원 할당
      • 제거: 종료되는 프로세스는 사용중이던 자원 해제 / 해당 PCB도 삭제 image3
      • 좀비 프로세스: 프로세스 비정상 종료 상태, 종료된 프로세스의 PCB가 프로세스 테이블에 남아 있는 경우

프로세스의 실행

  • 메모리에 적재된 프로세스들은 한정된 시간 동안 번갈아 가며 실행
    • 프로세스의 “실행” = 운영체제에 의해 “CPU 자원을 할당”받음
      1. CPU → 프로세스를 구성하는 명령어 및 데이터 인출
      2. 인출한 명령어 및 데이터 실행
      3. 운영체제 → CPU 자원 할당
  • 프로세스의 CPU 사용 시간
    • 타이머 인터럽트(timer interrupt)에 의해 제한
      • 타이머 인터럽트(=타임아웃 인터럽트): 시간이 끝났음을 알리는 인터럽트
    • 프로세스의 CPU 사용 절차
      1. 정해진 시간만큼 CPU 이용
      2. 타이머 인터럽트 발생
      3. CPU를 사용하던 프로세스의 문맥 백업
      4. 다음 프로세스에 CPU 양보
      5. 뒤이어 실행할 프로세스의 문맥 복구
        • ex) 프로세스 A 실행 → 타이머 인터럽트 → 프로세스 B 실행
        • 프로세스 A는 타이머 인터럽트가 발생하면, 지금까지의 중간 정보를 백업해야함
        • 그래야 다시 프로세스 A를 실행차례가 왔을 때, 작업 재개 가능
        • 문맥(context): 다시 작업을 재개하기 위해 기억해야 할 정보
          • 프로그램 카운터, 각종 레지스터 값, 메모리 정보, 실행을 위해 열었던 파일, 사용한 입출력 장치 등
          • 프로세스의 문맥은 해당 프로세스의 PCB에 명시 image4
    • Context switching(문맥 교환)
      • 기존 프로세스의 문맥은 PCB에 백업 하고, PCB에서 문맥 복구하여 새로운 프로세스 실행하는 일련의 과정
      • Context switching의 맹점
        • 잦은 context switching은 캐시 미스가 발생할 가능성이 높음
          • 메모리로부터 실행할 프로세스 내용을 가져오는 작업이 빈번 → 큰 오버헤드로 연결될 가능성 높음 image5

프로세스의 상태

  • 하나의 프로세스는 여러 상태를 거치며 실행됨
  • PCB를 통해 프로세스의 상태를 인식 및 관리
  • 각 상태 별 다이어그램 관계도
    • 생성 상태(new)
      • 프로세스 생성 중인 상태
      • 메모리에 적재되어 PCB를 할당 받은 상태
      • 프로세스 실행 준비를 마치고 준비 상태로 보냄
    • 준비 상태(ready)
      • 당장 실행은 가능한 상태 but 본인의 차례가 아니라 기다리는 상태
      • CPU를 할당 받으면, 그 즉시 실행 상태로 전환
        • 위와 같은 과정을 디스패치(dispatch)라 함
    • 실행 상태(running)
      • CPU를 할당받아 실행 중인 상태
        • 일정 시간만 CPU 사용 가능
      • 타이머 인터럽트가 발생하면, 준비 상태로 돌아감
      • 실행 도중 입출력 장치를 사용하여 입출력장치의 작업 종료시까지 기다려야 한다면, 대기상태가 됨
    • 대기 상태(blocked)
      • 곧장 실행이 불가능한 조건에 놓이는 상태
        • 입출력 작업을 요청하는 경우
        • 바로 확보할 수 없는 자원을 요청하는 경우
      • 실행 가능한 상태가 되면, 다시 준비 상태가 되어 CPU 할당을 기다림
    • 종료 상태(terminated)
      • 프로세스가 종료된 상태
      • 운영체제는 PCB 및 프로세스가 사용한 메모리를 정리함 image6
  • 블로킹 입출력 / 논블로킹 입출력
    • 블로킹 입출력(blocking I/O): 일반적인 “실행 상태 → 대기 상태 → 준비 상태” 입출력 방식
    • 논블로킹 입출력(non-blocking I/O): 대기 상태 없이, 입출력장치에게 입출력 작업을 맡기고 곧바로 이어질 명령어를 실행하는 입출력 방식 image7

2. 멀티프로세스 / 멀티스레드

멀티프로세스

  • 멀티프로세스(multi-process)
    • 동시에 여러 프로세스가 실행되는 것
    • 각기 다른 프로세스들은 자원을 공유하지 않음 → 독립적으로 실행 → 자원도 독립적으로 할당(PID, 파일 및 입출력장치 등) → 한 프로세스에 문제가 생겨도 다른 프로세스에 직접적 영향을 끼치지 않음 image8

멀티스레드

  • 멀티스레드(multi-thread)
    • 여러 프로세스를 동시에 실행하는 다중 스레드
    • 한 프로세스를 구성하는 코드를 동시에 실행하는 방법
    • 하나의 스레드는 각각 식별 가능한 고유 정보들로 구성
      • 스레드 ID / 프로그램 카운터 / 레지스터 값 / 스택 등
    • 스레드마다 다음에 실행할 주소를 가질 수 있고, 연산 과정의 임시 저장 값 확보 가능 image9

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

  • 가장 큰 차이점: 자원 공유 여부
    • 멀티프로세스: 서로 자원 공유 X
      • 한 프로세스에 문제가 생겨도, 다른 프로세스에는 지장이 없거나 적음
    • 멀티스레드: 같은 프로세스를 여러 스레드가 실행하기 때문에, 같은 프로세스의 자원 공유
      • 쉽게 협력 및 통신이 가능함
      • 한 스레드에 문제가 생기면 프로세스 전체의 문제가 될 수 있음 image10
  • 스레드 조인
    • 스레드 생성시 흔히 보는 연산
    • join(): 스레드를 생성한 주체가 ‘생성/실행된 스레드가 종료될 때까지 대기’해야함을 의미
      • ex) ‘main’이라는 스레드가 ‘a’스레드를 생성하면서 join을 호출했다면? → ‘main’ 스레드는 ‘a’스레드가 종료될 때까지 실행되지 않고 대기함

3. 프로세스 간 통신

  • 프로세스는 기본적으로 자원을 공유하지 않음
  • IPC(Inter-Process Communication, 프로세스 간 통신) → 프로세스 간에 자원을 공유하고 데이터를 주고 받을 수 있도록 하는 방법
  • IPC의 두 가지 유형
    • 공유 메모리: 데이터를 주고 받는 프로세스가 공통으로 사용할 영역을 두는 방식
    • 메시지 전달: 프로세스 간에 데이터를 주고 받을 때, 메시지의 형태로 주고받는 방식 image11

공유 메모리

  • 프로세스 간 공유하는 메모리 영역을 토대로 데이터를 주고 받는 통신 방식
    • 프로세스는 각각의 메모리 공간을 갖고 있음 → 다른 프로세스의 메모리 공간을 임의로 수정할 수 없음
    • 공유 메모리라는 특별 메모리 공간을 할당하여 프로세스 간 공유하며 읽고 쓸 수 있게
  • 공유 메모리 실행 방식
    • 시스템 콜 기반: 프로세스가 공유하는 메모리 영역 확보하는 시스템 콜 실행
    • 단순 공유변수 및 파일 활용: 공유 메모리 공간에 변수 및 파일을 쓰고 읽어들이는 방식
  • 공유 메모리의 특징
    1. 통신을 주고 받는 각 프로세스가 자신의 메모리 영역을 읽고 쓰는 것처럼 통신
    2. 데이터를 주고 받는 과정에서 커널의 개입이 거의 없음
      • 프로세스가 주고 받는 데이터는 커널 영역을 거치지 않는 경우가 다수
    3. 메시지 전달 방식보다 통신 속도가 빠름
    4. 데이터의 일관성 훼손 가능성
      • 레이스 컨디션 문제 발생 → 서로의 공유 메모리를 동시에 읽고 쓰기 때문

메시지 전달

  • 프로세스 간 주고 받는 데이터가 커널을 통해 메시지를 송수신하는 통신방식
    • 메시지를 보내는 수단과 받는 수단이 명확하게 구분되어 있음
      • 메시지를 보내는 시스템 콜: send()
      • 메시지를 받는 시스템 콜: recv()
    • 공유 메모리 기반과 달리 커널의 도움을 적극적으로 받을 수 있음 → 레이스 컨디션 / 동기화 등의 문제를 고려할 일이 적음
  • 메시지 전달 IPC의 대표 수단
    1. 파이프(pipe)
      • 단방향 프로세스 간 통신 도구
      • ex) 프로세스 A와 B
        • 프로세스 A가 파이프의 한 쪽 방향에서 데이터 write
        • 프로세스 B는 파이프 반대쪽으로 그 데이터를 읽을 수 있음 image12
      • 익명 파이프 vs 지명 파이프
        • 익명 파이프(unnamed pipe): 전통적인 단방향 통신 수단
        • 지명 파이브(named pipe)
          • FIFO, 양방향 통신 지원
          • 부모-자식 프로세스 간 통신 뿐 아니라, 임의의 프로세스 간 통신에도 사용 가능
    2. 시그널
      • 프로세스에게 특정 이벤트가 발생했음을 알리는 비동기적 신호
      • “적절히 시그널을 활용해 IPC를 수행할 수 있다” 정도로 인지
      • 시그널의 기본 동작
        • 대부분 프로세스 종료 / 무시 / 코어 덤프 생성
        • 코어 덤프
          • 주로 비정상적으로 종료되는 경우에 생성되는 파일
          • 프로그램이 특정 시점에 작업하던 메모리 상태 기록
          • 디버깅에 많이 활용
      • 시그널을 발생시키는 이벤트의 종류
        • 대부분 인터럽트와 관련
        • 사용자가 직접 정의 가능한 시그널도 있음
        • ex) Linux OS의 대표 시그널 image13
      • 시그널 발생 시, 이를 처리하기 위한 과정
        1. 하던 일 잠시 중단
        2. 시그널 핸들러 실행 → 시그널 처리해줌
        3. 실행 재개
          • 프로세스가 직접 특정 시그널 발생시킴
          • 프로세스가 직접 일부 시그널 핸들러를 재정의 하기도
      • 정리
        • 다른 IPC 기법들과 다르게 직접적 메시지 상호작용은 하지 않음
        • 비동기적으로 원하는 동작 수행이 가능한 좋은 수단 image14
    3. 소켓
      • 네트워크 관련 포스팅에서 추가 기술
    4. 원격 프로시저 호출(RPC)
      • 원격 코드를 실행하는 IPC 기술



chat_bubble 0

chat_bubble 댓글남기기

댓글남기기