fork는 유닉스 계열 운영체제에서 프로세스를 생성하기 위해 제공되는 시스템 콜이며, 호출된 프로세스(부모)를 복제하여 새로운 프로세스(자식)를 만든다. 이 시스템 콜은 프로세스 복제의 기본 메커니즘으로, 대부분의 유닉스 기반 시스템에서 동일한 동작을 보인다.
정의
fork()함수는 현재 실행 중인 프로세스의 주소 공간, 파일 디스크립터, 환경 변수, 프로세스 상태 등을 그대로 복사한 새 프로세스를 생성한다.- 호출 성공 시, 부모 프로세스에게는 자식 프로세스의 PID(Process ID)가 반환되고, 자식 프로세스에게는 0이 반환된다. 오류가 발생하면 ‑1이 반환되고
errno에 오류 원인이 설정된다.
역사
- 최초의
fork()구현은 1975년 발표된 UNIX Version 6에 포함되었으며, 이후 BSD, System V, Linux, macOS 등 다양한 유닉스 파생 시스템에 그대로 채택되었다. - 초기 구현은 프로세스 복제 시 전체 메모리를 복사했지만, 현대 구현에서는 Copy‑On‑Write(COW) 기법을 사용해 실제 메모리 복사를 지연시켜 효율성을 높인다.
동작 원리
- 프로세스 테이블 엔트리 복제: 부모의 프로세스 테이블 엔트리를 복사하여 자식 엔트리를 만든다.
- 주소 공간 복사: COW 방식에 따라 페이지 테이블만 복제하고 실제 물리 메모리는 필요 시 복사한다.
- 파일 디스크립터 복제: 부모와 자식이 동일한 파일 디스크립터를 공유하되, 파일 오프셋은 각각 독립적으로 유지된다.
- 시그널 핸들러 복사: 부모가 설정한 시그널 핸들러가 자식에게 그대로 전달된다.
- 리턴값 차별: 반환값을 기준으로 부모와 자식이 각각 다른 코드 경로를 수행할 수 있다.
관련 시스템 콜
- exec:
fork()후에 자식 프로세스가 새로운 프로그램 이미지를 로드하는 데 사용된다. 흔히fork‑exec패턴으로 프로세스 생성 후 실행 파일 교체가 이루어진다. - vfork: 부모 프로세스가 자식이
exec혹은_exit을 호출할 때까지 실행을 일시 중단하도록 설계된 변형이다. 효율성은 높지만 사용 시 주의가 필요하다. - clone: Linux에서 제공하는 시스템 콜로,
fork()와 달리 공유 자원(메모리, 파일 디스크립터 등)을 세부적으로 지정할 수 있다. 주로 스레드 구현에 활용된다.
사용 예시 (C 언어)
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(EXIT_FAILURE);
} else if (pid == 0) {
/* 자식 프로세스 */
printf("Child process, PID = %d
", getpid());
// exec, 작업 수행 등
_exit(0);
} else {
/* 부모 프로세스 */
printf("Parent process, child PID = %d
", pid);
// wait 등으로 자식 종료 대기 가능
}
return 0;
}
특징 및 제한
- 동시성:
fork()는 프로세스 복제 시점에 전역 변수나 파일 디스크립터 등이 복제되므로, 자식과 부모가 독립적으로 진행될 수 있다. 그러나 복제 직후에는 두 프로세스가 동일한 메모리 페이지를 공유하므로, 쓰기 작업이 발생하면 COW가 동작한다. - 시그널: 복제 시점에 설정된 시그널 핸들러가 그대로 복사된다. 자식이 시그널을 수신하면 부모와 별개로 처리된다.
- 리소스 제한: 시스템에 따라 한 사용자당 생성 가능한 프로세스 수(
ulimit -u)에 제한이 있다.fork()호출이 이 한계를 초과하면ENOMEM오류가 반환될 수 있다. - 스레드와의 호환성: 멀티스레드 프로그램에서
fork()를 호출하면 자식 프로세스는 호출 시점에 존재하던 하나의 스레드만 복제된다. 이 경우pthread_atfork핸들러를 이용해 재설정이 필요하다.
표준화
- POSIX.1-2001 및 이후 표준에
fork()가 정의되어 있다. 함수 시그니처는pid_t fork(void);이며, 오류 시errno에EAGAIN,ENOMEM,ENOSYS등이 설정된다.
참고 문헌
- IEEE Std 1003.1, “POSIX.1-2008 – System Interfaces”.
- Maurice J. Bach, The Design of the Unix Operating System, Prentice Hall, 1986.
- Robert Love, Linux System Programming, O'Reilly Media, 2013.