OS

[쉽게 배우는 운영체제] 3-1. 프로세스와 스레드: 프로세스

noahkim_ 2024. 12. 11. 21:55

조성호 님의 "쉽게 배우는 운영체제" 책을 정리한 포스팅 입니다

 

1. 개요

프로그램 vs 프로세스

구분 프로그램 프로세스
정의 어떤 작업을 어떤 데이터를 사용하여 할지 절차를 적어놓은 것 작업이 진행되고 있는 프로그램
상태 정적인 상태 (저장장치에 저장됨)
동적인 상태 (메모리에 올라와 실행 중)
저장 위치 디스크에 저장됨 RAM에 적재되어 실행됨
실행 여부 실행되지 않음 실행 중인 상태
예시 myapp.exe (실행 파일)
myapp.exe가 실행되어 프로세스 ID를 가지고 동작하는 상태

 

프로세스 자료구조

  • 프로세스를 관리하기 위한 운영체제의 데이터 구조
구분 설명
PID (Process ID)
프로세스의 고유 식별자
Process state
현재 상태 (실행, 대기, 종료 등)
Process Number 프로세스 번호
Program Counter
다음 실행할 명령어의 주소
Register CPU 레지스터 값
Memory limits
프로세스가 사용할 메모리 영역 정보 (코드, 데이터, 힙, 스택 영역 정보)

 

프로세스 상태

상태 설명 상황
Created (New)
프로그램이 메모리에 로드되고 PCB가 생성된 상태
- exec (실행 파일을 실행함)
Ready (Waiting) 실행 준비 완료, CPU 할당을 기다리는 상태  
Running CPU를 할당받아 실제 실행 중인 상태  
Blocked (Waiting)
I/O 요청 등으로 인해 CPU를 사용하지 못하고 대기 중
- 디스크/네트워크/입출력 요청
- 자원 획득 대기(lock)
Terminated 실행이 종료되어 자원이 회수된 상태 - 정상 종료
- 비정상 종료
- 강제 종료
Suspended 프로세스가 메모리에서 쫓겨난 상태 - 메모리가 부족할 경우
- 프로그램 오류로 실행이 미뤄질 경우
- 바이러스 프로세스로 판단될 경우
Stopped 프로세스가 일시적으로 실행을 중단
✅ 사용하던 데이터와 PCB 정보가 그대로 유지됨
✅ 멈춘 지점에서 재시작 가능
 

 

 

과정) Created (New)

더보기
  1. 프로그램이 메모리에 로드됨
  2. OS로부터 PCB 할당
  3. 실행 준비 완료 후 Ready 상태로 전환

 

과정) Ready (Waiting)

더보기
  1. Ready Queue에서 자기 순서를 기다림

 

과정) Blocked (Waiting)

더보기
  1. I/O 요청을 수행 중
  2. 요청한 I/O 작업이 완료될 때까지 대기 (입출력 장치별 대기 큐에서 기다림)

 

상태 변화) Running

더보기
상태 변화 메서드 상태
실행
dispatch(PID)
새로운 프로세스가 Running 상태로 이동
할당된 time slice 만료
timeout(PID)
Ready (Waiting) 상태로 이동
I/O 요청 발생
block(PID)
Blocked (Waiting) 상태로 이동
작업 완료
exit(PID)
Terminated(종료) 상태로 이동

 

상태 변화) Blocked (Waiting)

더보기
  • I/O 완료 후 Ready 상태로 이동
  • wakeup(PID) 호출 → Waiting(Ready) 상태로 전환

 

상태 변화) Terminated

더보기
상태 설명
정상 종료 exit(0)
오류로 인한 종료 exit(n)
정상 종료 요청  kill (SIGTERM), Ctrl + C (SIGINT)
강제 종료 kill -9 (SIGKILL)

 

상태 변화) Suspended

더보기

스왑 영역 (Swap Area)

  • Suspended 상태의 프로세스가 저장되는 영역
  • 디스크의 스왑 영역(Swap Space)에 저장됨
상태 설명
보류 대기 상태 (Swapped Out and Blocked)
- Blocked 상태에서 스왑됨 (I/O 요청 등의 이유)
- I/O 작업이 완료되면 다시 실행 대기
보류 준비 상태 (Swapped Out and Waiting)
- Ready 상태에서 스왑됨 
- 다시 메모리로 로드되면 Ready 상태로 복귀하여 실행 대기

 

상태 변화) Stopped

더보기
  • Ready or Blocked 전환됨
  • ✅ Ready 상태는 명령어로 제어됨
  •  Blocked 상태는 i/o 요청 중 중지됨
상태 변경 명령어 설명
일시 중지 Ctrl + Z
재시작 (포그라운드) fg
재시작 (백그라운드)  bg

 

Context Switching

  • CPU의 실행 주체가 변경되는 과정
  • 시분할 시스템에서는 여러 프로세스의 응답성과 효율성을 높이기 위해 CPU 실행 시간을 나누어 각 프로세스에 할당합니다.
  • 이 과정에서 CPU는 여러 프로세스를 번갈아 가며 실행합니다.

 

과정) Context Switching

더보기
  1. 현재 프로세스의 PCB 저장: 실행 중인 프로세스의 정보를 PCB에 저장
  2. 새로운 프로세스의 PCB 로드: 실행할 프로세스의 PCB를 메모리에서 로드하고, 레지스터 및 PC 정보를 복원
  3. CPU 제어권 전달: CPU가 새로운 프로세스를 실행하도록 전환함

 

발생하는 상황) Context Switch

더보기
구분 설명
멀티태스킹
여러 프로세스를 번갈아 실행하기 위해 CPU를 교체
인터럽트
I/O 요청, 시스템 호출, 외부 이벤트로 인해 실행 중인 프로세스가 일시 정지됨
프로세스 우선순위 변경
스케줄러가 높은 우선순위의 프로세스를 실행하기 위해 전환

 

종류) Context Switching

더보기
구분 설명
프로세스 간 전환
두 개의 서로 다른 사용자 프로세스 간에 이루어짐
스레드 간 전환
동일한 프로세스 내에서 스레드 전환

 

파일 접근 구조

종류 설명
FDT (File Descriptor Table) 프로세스 오픈 파일 테이블
System Open-File Table
시스템 오픈 파일 테이블
Active vnode table
파일 시스템 캐싱 테이블 (inode 정보)

 

과정) 파일 읽기

더보기
  1. FDT에서 해당 파일인 fd에 해당하는 System Open-File Table 엔트리를 찾음
  2. inode 참조
    • Active Vnode Table에서 캐싱 여부 확인
    • 캐싱이 안되어있다면, System Open-File Table(disk)에서 inode 참조
  3. 데이터 블록 읽기
    • inode를 통해 데이터 블록 접근

 

2. 프로세스 구조

  • 프로세스가 사용하는 작업 공간
메모리 영역 설명 특징
Text Area 프로그램의 코드가 저장된 곳
 
Data Area 변수 및 데이터가 저장되는 영역 - Initialized data: 초기값이 있는 변수들 
- Uninitialized data (BSS): 초기값이 없는 변수들
Stack Area 함수 호출 시 생성되는 데이터를 저장하는 임시 메모리 공간 - 스택 프레임: 지역 변수, 매개 변수, 반환 주소, 반환 값
- 함수 호출이 끝나면 해당 메모리는 자동으로 해제됨
Heap Area 런타임에 동적으로 할당되는 데이터 영역
- 포인터를 통해 접근 가능 
- 프로그램이 종료될 때까지 메모리 해제되지 않음
- 수동 관리 필요

 

3. 프로세스 계층 구조

커널 프로세스와 init 프로세스

개념 설명 특징
커널 프로세스 커널 내부에서 동작하는 프로세스 시스템 자원 관리, 하드웨어 제어
init 프로세스 커널이 부팅 완료 후 최초로 실행하는 사용자 프로세스
모든 사용자 프로세스의 조상 (PID 1번)
자식 프로세스를 생성함

 

프로세스 연산

구분 fork() exec()
목적 새 프로세스 생성 프로세스 내용 교체
PID 자식에 새 PID 유지
메모리 COW 기반 복제 완전 교체
PCB 새로 생성 기존 PCB 재사용
실행 결과 부모 + 자식 실행 새 프로그램 실행
주 사용처 프로세스 생성 다른 프로그램 실행

 

코드) fork()

더보기
#include <stdio.h>
#include <unistd.h>

int main() {
    int pid = fork();

    if (pid > 0) {
        printf("부모 프로세스\n");
    } else if (pid == 0) {
        printf("자식 프로세스\n");
    } else {
        printf("fork 실패\n");
    }

    return 0;
}

 

코드) exec()

더보기
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("exec 실행 전\n");

    execl("/bin/ls", "ls", NULL);

    printf("exec 실행 후\n");  // 실행 안 됨
    return 0;
}

 

장점

장점 설명
동시 처리
여러 사용자의 요청을 처리하기 위해 fork()로 자식 프로세스를 여러 개 만들어 각 요청을 분배하기 용이함
자원 회수 용이 부모-자식 관계로 관리.
➡️ 종료 상태 추적 가능

 

고아 프로세스

  • 부모 프로세스가 먼저 종료된 자식 프로세스
  • ⚠️ 자식 프로세스의 자원이 정상적으로 반환되지 못함
  • ➡️ 커널이 init 프로세스를 부모로 자동 재할당하여 자식의 자원을 회수함

 

좀비 프로세스

  • 실행이 종료되었지만 부모 프로세스가 종료 상태를 회수하지 않아 프로세스 테이블에 남아있는 상태
  • ⚠️ PID 슬롯을 차지하여 새 프로세스 생성에 영향을 줄 수 있음
  • ➡️ 부모가 wait()을 호출하여 자식의 자원을 회수해야 함

 

5. 프로세스 실행 과정

프로세스 그룹

  • 여러 프로세스를 하나의 그룹으로 묶어 터미널에서 관리하기 위한 개념

 

특징
특징 설명
커널의 터미널 제어 - 터미널 제어권: 터미널은 한 번에 하나의 프로세스 그룹만 포어그라운드에서 제어함
- 하위 프로세스 실행: 같은 프로세스 그룹에 속해 있으면 같은 터미널 제어권을 공유함
프로세스 그룹 제어
터미널은 프로세스 그룹의 제어권을 가집니다.
즉, 어떤 프로세스가 터미널의 입력을 받거나 출력을 담당할지를 결정합니다.
PGID (Process Group ID) 프로세스 그룹에는 고유한 식별자인 PGID가 부여됩니다.
같은 그룹은 터미널에서 파이프라인으로 연결되어 그룹핑됩니다. 

 

 

출처