프로세스 생성 기법

2025. 1. 18. 14:18·운영체제/프로세스 상태와 계층 구조

프로세스 생성 기법

운영체제는 새로운 프로세스를 생성하기 위해 보통 두 가지 주요 시스템 호출을 사용한다. 하나는 fork() 로 부모 프로세스를 복제하여 자식을 만들고, 다른 하나는 exec() 로 새로운 프로그램으로 메모리 공간을 교체하는 방식이다. 이 글에서는 fork()와 exec()가 어떻게 동작하는지, 왜 이런 방식으로 자식 프로세스가 만들어지고 실행되는지 좀 더 자세히 살펴본다.

 


1. fork() — 부모 프로세스 복제

1.1 개념

  • fork() 는 부모 프로세스를 복제해 새로운 자식 프로세스를 생성하는 시스템 호출이다.
  • 자식 프로세스는 부모 프로세스의 대부분 리소스(메모리, 열린 파일 디스크립터, 환경 변수 등)를 상속받는다.
  • PID(프로세스 식별자)는 새로 할당되므로, 부모와 자식은 서로 다른 PID를 가진다.

1.2 반환값과 흐름

fork()를 호출하면, 부모 프로세스에는 자식의 PID가 반환되고, 자식 프로세스에는 0이 반환된다. 이렇게 두 프로세스가 동일한 코드 지점에서 실행을 이어가지만, 반환값을 통해 분기 처리가 가능하다.

pid_t pid = fork();

if (pid < 0) {
    // fork 실패
} else if (pid == 0) {
    // 여기는 자식 프로세스 흐름
} else {
    // 여기는 부모 프로세스 흐름
}

1.3 Copy-on-Write 최적화

일부 운영체제(예: Linux)는 fork() 호출 시 메모리 페이지를 실제로 즉시 복사하지 않고, Copy-on-Write(COW) 기법을 사용한다.

  • 동작 원리: 부모와 자식이 동일한 물리 메모리를 공유하면서 읽기만 할 때는 복사하지 않고, 어느 한 쪽에서 쓰기 연산이 발생하면 그 시점에 해당 페이지만 실제 복사한다.
  • 장점: fork() 호출 직후 바로 exec()를 진행하는 경우, 대량의 메모리를 복사할 필요가 없어 시스템 자원과 시간을 절약할 수 있다.

Image

(그림 출처: 혼자 공부하는 컴퓨터 구조 + 운영체제)

 


2. exec() — 새로운 프로그램으로 갈아입기

2.1 개념

  • exec() 는 현재 프로세스의 메모리 공간(코드·데이터·스택 등)을 새로운 프로그램으로 덮어쓰는 시스템 호출이다.
  • 여러 변형(execl, execv, execvp, 등)이 존재하며, 프로그램 경로와 인자 전달 방식 등에 차이가 있다.

2.2 동작 과정

  1. 프로세스(일반적으로 자식) 가 exec() 계열 함수를 호출한다.
  2. 이전 코드와 데이터는 사라지고, 지정한 프로그램의 코드와 데이터를 메모리에 로드한다.
  3. 프로세스의 PID는 유지되지만, 실행 이미지가 완전히 바뀌어 새 프로그램을 시작한다.
  4. 성공 시 exec() 호출 이후의 코드는 절대 실행되지 않는다(프로그램이 새로 시작되므로).

2.3 메모리 영역 교체와 초기화

  • 코드 영역: 새 프로그램의 기계어 코드로 교체
  • 데이터 영역: 전역 변수, 초기화된 데이터, BSS(미초기화 데이터) 등이 새롭게 설정
  • 스택 영역: 새 프로그램의 스택 초기 상태로 재구성
  • 힙 영역: 새로 시작하므로 기존 동적 할당 정보는 무효화(초기화)
  • 열린 파일: 일반적으로 기존에 열려 있던 파일 디스크립터 중 일부는 그대로 유지 가능(표준 입출력 등)

Image

(그림 출처: 혼자 공부하는 컴퓨터 구조 + 운영체제)

 


3. 예시: bash 셸에서 ls 실행

  1. 사용자가 셸(bash)에서 ls 명령을 입력한다.
  2. 셸 프로세스는 fork()를 호출하여 자신의 복제본(자식 프로세스)을 만든다.
  3. 새로 만들어진 자식 프로세스는 exec()를 호출해 ls 프로그램을 메모리에 로드한다.
  4. 자식 프로세스는 이제 셸 코드가 아닌 ls 코드를 수행하면서 디렉토리 목록을 출력한다.
  5. 자식 프로세스는 작업을 마치고 종료(exit()), 부모(셸)는 기존 코드로 돌아가 다음 명령을 기다린다.

Image

(그림 출처: 혼자 공부하는 컴퓨터 구조 + 운영체제)

 


4. 부모 프로세스, 자식 프로세스가 동일 코드를 실행하는 경우

fork() 후에 자식 프로세스가 exec()를 호출하지 않는 상황도 있다. 이 경우 자식 프로세스는 부모와 동일한 코드를 동시에 병렬로 수행하게 된다.

  • 대표적 사례: 서버 프로그램에서 여러 fork() 호출을 통해 자식 프로세스를 다수 생성하고, 자식들도 동일한 로직(예: 클라이언트 연결 처리)을 병렬로 수행.
  • 주의: 전역 변수, 파일 핸들 등의 자원은 서로 별도로 존재(복사되거나 COW 공유)하므로, 동기화/충돌 처리를 고려해야 한다.

 


5. 프로세스 계층 구조와 반복

운영체제에서 부모가 자식을 생성하고(= fork()), 자식이 새로운 프로그램을 로드해 실행(exec())하면서, 프로세스 계층 구조가 형성된다.

  • 부모 프로세스 → 자식 프로세스 → (또 다른) 자식 프로세스 …
  • 각 자식은 필요에 따라 새 프로그램을 로드해 별도의 작업을 수행할 수 있다.

결과적으로, 부팅 시점에 생성된 최초 프로세스(PID 1)에서 시작해, 무수히 많은 프로세스들이 이러한 fork() & exec() 과정을 반복함으로써 다양한 프로그램이 동시에 실행된다.

 


6. 요약

  1. fork()
    • 부모 프로세스를 복제하여 자식 프로세스를 생성하는 시스템 호출.
    • 부모의 메모리·파일 디스크립터·환경 등을 상속받는다.
    • Copy-on-Write 최적화를 통해 효율적 메모리 사용 가능.
  2. exec()
    • 현재 프로세스(대개 자식)의 메모리 공간을 새로운 프로그램으로 교체.
    • PID는 그대로 유지되지만, 실행 코드와 데이터는 전혀 다른 내용으로 덮어쓰여진다.
  3. 실행 흐름
    • fork() 직후에는 부모·자식이 동일 코드를 실행한다(반환값으로 분기).
    • 자식이 곧바로 exec()를 호출해 새 프로그램으로 옷을 갈아입으면 새로운 프로세스로 동작한다.
    • exec()를 사용하지 않으면 부모와 동일 코드를 병렬로 실행하기도 한다.

 


참고 자료

  • 혼자 공부하는 컴퓨터 구조 + 운영체제
  • Operating System Concepts (A. Silberschatz, P.B. Galvin, G. Gagne)
  • Modern Operating Systems (A.S. Tanenbaum, H. Bos)
  • Linux fork() manual, Linux exec() manual

 

'운영체제 > 프로세스 상태와 계층 구조' 카테고리의 다른 글

프로세스 계층 구조 (Process Hierarchy)  (0) 2025.01.18
프로세스 상태  (0) 2025.01.16
'운영체제/프로세스 상태와 계층 구조' 카테고리의 다른 글
  • 프로세스 계층 구조 (Process Hierarchy)
  • 프로세스 상태
iOS Developer
iOS Developer
myungsun-e 님의 블로그 입니다.
  • iOS Developer
    myungsun-e
    iOS Developer
  • 전체
    오늘
    어제
    • 분류 전체보기 (25)
      • 컴퓨터 네트워크 (11)
        • 응용계층 (11)
      • 운영체제 (14)
        • 운영체제 시작하기 (2)
        • 프로세스 상태와 계층 구조 (3)
        • 프로세스와 스레드 (1)
        • CPU 스케줄링 (3)
        • 동기화란 (2)
      • iOS (0)
        • Swift-문법 (0)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    IOS
    컴퓨터 네트워크
    SWIFT
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
iOS Developer
프로세스 생성 기법
상단으로

티스토리툴바