리눅스 프로세스 식별자와 생성 방식 정리 – PID, PPID, exec, fork 차이
리눅스에서 모든 실행 중인 작업은 프로세스(Process) 형태로 관리되며, 이들은 식별자와 시스템 콜을 통해 생성·제어됩니다. 이번 글에서는 PID, PPID, UID, GID 같은 식별자와 함께, 프로세스를 생성하는 핵심 방식인 fork()와 exec()의 차이를 명확하게 설명합니다.
1. 리눅스 프로세스 식별자
1.1 PID (Process Identifier)
- 정의: 시스템에서 실행 중인 각 프로세스를 고유하게 식별하기 위한 정수 값
- 특징:
- 시스템 내에서 중복되지 않음
- 프로세스 관리 및 추적에 필수적
ps -ef | grep bash # 실행 중인 프로세스의 PID 확인
1.2 PPID (Parent Process Identifier)
- 정의: 부모 프로세스의 PID
- 용도: 부모-자식 프로세스 간의 관계를 파악할 때 사용
ps -o pid,ppid,comm # PID와 PPID 확인
1.3 UID (User Identifier) & GID (Group Identifier)
- UID: 프로세스를 실행한 사용자의 ID
- GID: 해당 사용자가 속한 기본 그룹 ID
대부분의 경우, UID와 GID는 부모 프로세스로부터 상속받습니다.
ps -o pid,user,uid,gid,comm
2. 프로세스 생성 방식
리눅스에서는 주로 fork()와 exec() 시스템 콜을 통해 프로세스를 생성하거나 교체합니다.
2.1 fork() – 프로세스 복제
- 정의: 현재 프로세스를 복제하여 자식 프로세스를 생성
- 특징:
- 부모와 자식이 동일한 코드와 데이터를 가지지만, 별도의 PID를 가짐
- 리턴 값 기준 분기:
0: 자식 프로세스- 양수(PID): 부모 프로세스
예제 코드
#include <stdio.h>
#include <unistd.h>
int main() {
int pid = fork();
if (pid == 0) {
printf("자식 프로세스입니다. PID: %d\\n", getpid());
} else {
printf("부모 프로세스입니다. PID: %d, 자식 PID: %d\\n", getpid(), pid);
}
return 0;
}
🔹 새로운 프로세스를 만들고, 독립적으로 실행됩니다.
2.2 exec() – 프로세스 이미지 교체
- 정의: 현재 프로세스의 메모리 공간을 새 프로그램으로 완전히 교체
- 특징:
- PID는 그대로 유지되지만, 이전 프로그램은 메모리에서 완전히 사라짐
- 주로
fork()와 함께 사용
셸 예시
exec ls -l
→ 현재 셸이 종료되고 ls -l 명령만 실행
2.3 fork() + exec() 조합 (실무에서 가장 흔함)
fork()로 자식 생성- 자식에서
exec()를 호출하여 다른 프로그램 실행
예: 터미널에서 명령어 실행 시 대부분 이 구조로 작동
3. 프로세스 생성 방식 비교 요약
| 방식 | 동작 설명 | PID 변화 | 용도 |
|---|---|---|---|
fork() |
부모 프로세스를 복제하여 자식 생성 | 새 PID 부여 | 새로운 프로세스 생성 |
exec() |
현재 프로세스를 다른 프로그램으로 교체 | 변화 없음 | 프로그램 실행 및 전환 |
4. 관계 구조도 (시각화)
┌────────────┐
│ 부모 프로세스 (PID 1000) │
└────┬───────┘
│ fork()
▼
┌────────────┐
│ 자식 프로세스 (PID 1020, PPID 1000) │
└────┬───────┘
│ exec("/bin/ls")
▼
┌────────────┐
│ ls 프로세스 (PID 1020) │
└────────────┘
질문 정리
Q1. exec() 호출 시 기존 프로그램은 완전히 사라지나요?
- exec는 기존 프로세스 이미지를 완전히 교체합니다. 이전 코드, 데이터, 힙, 스택 등 모두 제거됩니다.
Q2. PID는 시스템 재부팅 후에도 유지되나요?
- 아니요. PID는 재부팅 시 초기화되며, 시스템에서 다시 1부터 할당됩니다.
Q3. 자식 프로세스가 종료되었을 때 PID는 자동으로 해제되나요?
- 아닙니다. 부모 프로세스가
wait()로 종료 상태를 수거해야 PID가 해제됩니다. 그렇지 않으면 좀비 프로세스로 남습니다.
Q4. fork 없이 exec만 사용할 수 있나요?
- 가능합니다. 하지만 기존 프로세스가 덮어쓰기되기 때문에 일반적인 셸 환경에서는 fork 후 exec 구조가 더 자주 사용됩니다.
Q5. exec을 사용하면 PID가 유지되는데, 왜 새로운 프로세스처럼 보이나요?
- 프로세스 ID는 같지만, 메모리 공간이 완전히 교체되었기 때문입니다. 실제로는 새로운 프로그램이 실행 중인 기존 껍데기라고 볼 수 있습니다.
마무리 정리
| 항목 | 설명 |
|---|---|
| PID | 프로세스의 고유 식별자 |
| PPID | 부모 프로세스의 PID |
| UID/GID | 사용자 및 그룹 정보, 부모로부터 상속 |
| fork() | 새 자식 프로세스 생성, PID 변경됨 |
| exec() | 현재 프로세스를 새 프로그램으로 교체, PID 유지됨 |
리눅스 시스템의 프로세스 식별자와 생성 방식은 서버 운영, 셸 스크립트 작성, 시스템 개발의 기초 중의 기초입니다. 실습을 통해 fork와 exec의 동작 원리를 직접 체험해보면 더욱 명확히 이해할 수 있습니다.
댓글남기기