fork 创建进程
fork 是Unix中创建新进程的唯一系统调用,其行为独特且精妙。
基本行为:调用一次,返回两次。在父进程中,fork 返回新创建子进程的PID;在子进程中,fork 返回 0。通过返回值区分父子进程。
写时复制(Copy-on-Write):子进程创建时并不真正复制父进程的物理内存,而是共享同一物理页,但页表标记为只读。当任一进程尝试写入时,触发缺页故障,内核分配新页并复制数据,然后将页表权限改为可写。这种延迟复制策略极大减少了 fork 的开销,特别是当子进程立即调用 execve 时——子进程根本不需要父进程的数据副本。
子进程状态:子进程是父进程的完全拷贝,包括代码段、数据段、堆、栈、打开文件表、信号处理设置等。但子进程拥有独立的PID、独立的内存空间(逻辑上完全独立)。
执行顺序不确定性:父子进程是并发执行的,它们的指令交错顺序由操作系统调度器决定。虽然通常父进程先执行以减少调度开销,但从程序正确性角度不应依赖任何特定的执行顺序。
示例:
pid_t pid = fork();
if (pid == 0) { /* 子进程 */
printf("child: %d\n", ++x);
} else { /* 父进程 */
printf("parent: %d\n", --x);
}父进程和子进程中的 x 是各自独立的副本,修改互不影响。
链接到
- 上一个知识点:8.8 进程上下文
- 下一个知识点:8.10 回收子进程wait