fork() 是 Unix/Linux 創建新進程的核心系統調用。調用一次,返回兩次:
errno#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid;
int n = 4;
printf("Before fork: PID=%d, n=%d\n", getpid(), n);
pid = fork(); // 此處分叉為兩個進程
if (pid < 0) {
perror("fork failed");
return 1;
} else if (pid == 0) { // 子進程
n++;
printf("Child: PID=%d, PPID=%d, n=%d\n", getpid(), getppid(), n);
} else { // 父進程
n--;
printf("Parent: PID=%d, Child PID=%d, n=%d\n", getpid(), pid, n);
}
printf("End: PID=%d, n=%d\n", getpid(), n);
return 0;
}
Before fork: PID=1234, n=4
Child: PID=1235, PPID=1234, n=5
Parent: PID=1234, Child PID=1235, n=3
End: PID=1235, n=5
End: PID=1234, n=3
關鍵觀察:
n 副本,修改互不影響getppid() 返回父進程 PIDtask_struct,複製父進程大部分欄位pidmap 分配唯一 PIDmm_struct、頁表、VMA 鏈表(Copy-on-Write 標記頁面只讀)files_struct,引用計數 +1,父子共享打開檔案偏移量sighand_structtask_list、PID 雜湊表exec() 時(子進程立即替換映像,無實際複製)| errno | 原因 |
|---|---|
| EAGAIN | 進程數達上限(RLIMIT_NPROC 或 /proc/sys/kernel/pid_max) |
| ENOMEM | 內核內存不足,無法分配 task_struct、頁表等 |
CLONE_VM、CLONE_FS、CLONE_FILES、CLONE_SIGHAND、CLONE_THREAD),執行緒庫(pthread)底層即基於 clone()。_exit() 而非 exit(),避免雙重刷新 stdio 緩衝區wait()/waitpid() 回收子進程,防止殭屍進程