fork 进程创建与同步
概要:通过示例代码逐行解析 fork 系统调用:fork 创建子进程、父子进程分支执行,以及父进程通过 wait 等待子进程退出实现同步。
int pid;
pid = fork();
if(pid > 0){
printf("parent: child=%d\n", pid);
pid = wait();
printf("child %d is done\n", pid);
} else if(pid == 0){
printf("child: exiting\n");
exit();
} else {
printf("fork error\n");
}
代码逐行解析
-
变量声明
int pid;声明一个整型变量
pid,用于存储fork()系统调用的返回值。 -
创建子进程
pid = fork();fork()是系统调用,它会创建一个当前进程的副本(子进程)。调用后,系统中的进程数+1。- 在父进程中:
fork()返回新创建的子进程的进程ID(PID,一个大于0的正整数)。 - 在子进程中:
fork()返回 0。 - 如果创建失败:
fork()返回 -1。
- 在父进程中:
-
根据
fork()的返回值分流执行 这是一个典型的三路分支,对应上述三种情况。-
父进程执行路径 (
pid > 0)if(pid > 0){ printf("parent: child=%d\n", pid); // 1. 打印子进程的PID pid = wait(); // 2. 调用wait(),阻塞等待任意一个子进程结束 printf("child %d is done\n", pid); // 3. 子进程结束后,打印其PID }- 父进程打印它刚创建的子进程的ID。
wait()系统调用使父进程挂起(阻塞),直到它的一个子进程终止(本例中就是它刚创建的那个)。wait()返回被终止的子进程的PID,并回收其资源(防止成为“僵尸进程”)。- 父进程被唤醒,打印已结束的子进程PID。
-
子进程执行路径 (
pid == 0)else if(pid == 0){ printf("child: exiting\n"); // 子进程打印信息 exit(); // 子进程调用exit()终止自己 }- 子进程打印一条信息。
exit()系统调用立即终止当前进程(子进程)。子进程的所有资源会被内核释放,并向父进程发送一个“终止信号”。注意:标准C库中exit()通常需要一个状态参数,如exit(0)。
-
错误处理路径 (
pid < 0,通常是-1)else { printf("fork error\n"); // 打印创建失败的错误信息 }
-
可能的输出示例
由于进程调度顺序不确定,父进程的 printf 和子进程的 printf 输出可能交错,但逻辑顺序是确定的。
一种典型的输出顺序是:
parent: child=12345
child: exiting
child 12345 is done
- 第一行是父进程在
wait()之前打印的。 - 第二行是子进程打印的。
- 第三行是子进程结束后,父进程从
wait()返回后打印的。
另一种可能的输出顺序是:
child: exiting
parent: child=12345
child 12345 is done
留下评论