[OS] 프로세스 생성과 종료

2025. 2. 24. 21:25·CS/OS

프로세스의 생성


Unix에서 프로세스 생성은 fork()와 exec() 시스템 콜을 통해 이루어진다.
부모 프로세스가 자식 프로세스를 생성하며, 이러한 구조가 반복되면 트리(Tree) 형태의 프로세스 계층이 형성된다.

 

Fork()

부모 프로세스가 자식 프로세스를 생성하려면 fork() 시스템 콜을 호출해야 한다.
하지만 부모 프로세스가 직접 자식을 생성하는 것이 아니라, 운영체제(OS)가 부모와 동일한 자식 프로세스를 생성하는 방식이다.

이때 중요한 점은 fork()가 부모 프로세스의 프로그램 카운터(PC)를 포함한 메모리 상태를 그대로 복사한다는 것이다.

 

부모 프로세스와 자식 프로세스의 메모리

그렇다면 부모 프로세스의 가상 메모리(Virtual Memory) (코드, 스택, 힙 등)를 자식 프로세스가 그대로 공유할까?
일반적으로 자식 프로세스는 독립적인 가상 메모리 공간을 가진다. 

현대 OS 시스템에서는 성능 최적화를 위해 특정 공유 자원을 함께 사용하다 복사를 실행합니다.

Copy On Write

현대 OS는 fork() 일어나는 즉시 독립적인 가상 메모리 공간을 생성하지 않습니다. 읽기 전용으로 공유하다가 어느 한쪽이 메모리를 수정하려 할 때 복사본을 생성하는 방식입니다. 불필요한 메모리 낭비 없이 프로세스를 생성합니다.

 

부모 프로세스와 자식 프로세스의 구분

fork()의 반환값을 이용해 부모와 자식을 구별할 수 있다.

  • 자식 프로세스: fork()의 반환값이 0
  • 부모 프로세스: fork()의 반환값이 자식 프로세스의 PID(Process ID)

부모 프로세스가 자식 프로세스의 작업이 끝날때 까지 기다리는 wait() 와 동시에 자식프로세스와 부모 프로세스가 작업하는 경우가 있습니다.

Exec()

fork()를 한 이후 다른 프로그램을 실행시키는 시스템 콜이 exec() 입니다. exec() 시스템 콜이 일어난다면 다른 프로그램을 실행시키 위해 기존의 Virtual Memory에 존재하는 모든 정보를 초기화 시킨 다음 새로운 프로그램을 덮어 씌운뒤 실행을 합니다.

즉, 현재 실행중인 파일을 다른 실행파일로 변환하는 작업입니다.

 

왜 유닉스는 이런 복잡한 짓을? fork() -> exec()


그냥 바로 Window의 CreateProcess처럼 생성하면 되지않나? 라는 의문이 들껍니다.

그 이유를 알기 위해서는 Unix의 쉘 동작 방식을 알아야합니다.

 

쉘의 구현을 위한 분리

하나의 상황을 가정해 봅시다. 우리가 Unix의 쉘에서 ls를 입력한다고 생각해봅시다. 그럼 유닉스 에서는 다음과 같은 과정이 일어납니다.

  1. 쉘은 fork() 시스템 콜로 자기 자신를 복사.
  2. 자식 프로세스 exec()를 호출하여 ls 실행
  3. 부모 쉘은 다음 명령어를 기다립니다.

만약 fork()없이 exec()만을 실행한다면 ls 실행이후 쉘이 종료됩니다.

 

쉘의 fork()와 exec() 중간의 작업

 fork()이후 exec()일어나기 전에 다양한 작업이 수행이 가능하다.

pid_t pid = fork(); // 복사본 생성
if (pid == 0) { // 자식 프로세스
    // 여기서 준비 작업!
    freopen("output.txt", "w", stdout); // 출력을 파일로 리다이렉션
    execl("/bin/ls", "ls", NULL); // ls 실행
}

 

프로세스의 종료


프로세스가 종료되는 상황은 크게 두 가지로 나눌 수 있다.

  1. 자식 프로세스가 정상적으로 작업을 완료하고 종료하는 경우
  2. 부모 프로세스가 먼저 종료되는 경우

exit() 시스템 콜과 프로세스 종료

프로세스는 종료될 때 exit() 시스템 콜을 호출하여 운영체제(OS)에 자신의 종료 상태를 알리고 자원을 반환한다.

자발적 종료 (Normal Termination)

  • 프로세스가 마지막 명령문을 실행한 후 exit() 시스템 콜을 호출하여 정상적으로 종료됨.
  • 자식이 종료되었을 때 부모가 그 상태를 수거하는 과정
  • 명시적으로 exit()를 호출하지 않아도, main() 함수가 리턴되면 컴파일러가 자동으로 exit()를 삽입하여 종료를 처리함.

비자발적 종료 (Abnormal Termination)

  • 부모 프로세스가 자식을 강제 종료하는 경우
  • 자식 프로세스가 시스템 자원을 초과 요청하는 경우 (예: 메모리 초과)
  • 자식 프로세스가 더 이상 수행할 작업이 없거나 필요하지 않은 경우
  • 사용자가 kill 또는 Ctrl + C(SIGINT), Ctrl + Z(SIGTSTP) 등의 신호를 입력하여 강제 종료하는 경우

부모 프로세스가 먼저 종료되는 경우

일반적으로 부모 프로세스가 종료되기 전에 자식 프로세스가 먼저 종료되도록 한다.
그러나 부모가 먼저 종료되면, 운영체제는 고아 프로세스(orphan process) 가 되지 않도록 init 프로세스(PID 1)가 이를 대신 관리하게 된다. 즉, 고아 프로세스는 작업이 완료되면 init 프로세스에서 작업 종료를 알리고 init 프로세스가 고아 프로세스의 상태를 수거합니다.

'CS > OS' 카테고리의 다른 글

[OS] 멀티 레벨 피드백 큐  (0) 2025.03.07
[OS] CPU 스케줄링  (0) 2025.03.06
[OS] 프로그램 실행 작업 순서와 컴퓨터 시스템 구조  (0) 2025.02.24
[OS] Process 와 Thread  (0) 2025.02.23
[운영체제] 운영체제란?  (0) 2024.11.11
'CS/OS' 카테고리의 다른 글
  • [OS] 멀티 레벨 피드백 큐
  • [OS] CPU 스케줄링
  • [OS] 프로그램 실행 작업 순서와 컴퓨터 시스템 구조
  • [OS] Process 와 Thread
절박한개발자
절박한개발자
깃허브 주소 : https://github.com/Kzerojun
  • 절박한개발자
    절박한개발
    절박한개발자
  • 전체
    오늘
    어제
    • 분류 전체보기 (99)
      • Server (5)
      • 프로젝트 (7)
      • Spring (7)
      • AI (1)
      • JPA (6)
      • JAVA (7)
      • Backend (3)
      • WEB (3)
      • 알고리즘-이론 (6)
      • 알고리즘-문제 (28)
      • CS (24)
        • 데이터베이스 (8)
        • Network (5)
        • OS (10)
        • LINUX (1)
      • 개발면접준비 (1)
      • 기타 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    CPU
    2
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
절박한개발자
[OS] 프로세스 생성과 종료
상단으로

티스토리툴바