1. 理解fork函数的基本行为
在Unix/Linux系统编程中,fork()是一个让人又爱又恨的系统调用。第一次接触它时,最让人困惑的就是:明明只调用了一次fork(),为什么会有两个返回值?这个问题困扰过无数初学者,包括当年的我。让我们先从一个简单的代码示例开始:
c复制#include <unistd.h>
#include <stdio.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
printf("这是子进程,我的PID是%d\n", getpid());
} else if (pid > 0) {
printf("这是父进程,我的PID是%d,子进程PID是%d\n", getpid(), pid);
} else {
perror("fork失败");
return 1;
}
return 0;
}
运行这个程序,你会看到类似这样的输出:
code复制这是父进程,我的PID是1234,子进程PID是1235
这是子进程,我的PID是1235
注意:实际运行时的PID数字会不同,每次运行都会变化
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. fork的工作原理深度解析
2.1 进程复制的本质
当调用fork()时,操作系统会创建一个几乎完全相同的进程副本。这个"几乎"很关键,因为虽然两个进程有相同的代码、数据、堆栈和打开的文件描述符等,但它们确实有一些关键区别:
- 进程ID(PID)不同
- 父进程ID(PPID)不同(子进程的PPID是父进程的PID)
- 子进程不会继承父进程的内存锁、文件锁和信号量等
- 子进程的未决信号集被清空
- 子进程不会继承父进程的定时器
2.2 返回值的魔法
fork()的独特之处在于它只被调用一次,但返回两次——一次在父进程,一次在子进程。这是如何实现的?
- 在父进程中,fork()返回新创建的子进程的PID
- 在子进程中,fork()返回0
- 如果出错,fork()返回-1(在父进程中)
这种设计非常巧妙,因为它允许父进程和子进程通过检查返回值来区分自己是谁,从而执行不同的代
