fork() 小记

fork

在 UNIX/Linux 中,fork() 用于创建当前进程的子进程

vfork() 在新建子进程后,将父进程阻塞

子进程

fork 出来的子进程,与父进程有着完全一致的变量值和程序计数器。

对于完全一致的变量值,需要指出的是,父进程和子进程拥有完全不同的内存空间;

对于完全一致的程序计数器,这意味着,在 fork 调用之前的父进程中的全部语句,子进程将不会执行

那么问题来了,对于产生子进程的那条 fork 语句,子进程将如何执行呢?

简单来说,子进程仍然会执行这条 fork 语句,但是并不产生新的进程(不妨使用「反证法」,如果继续产生新的子进程,那么这将是一个无限递归的过程,那么内存岂不是爆满了),只会拥有返回值。

返回值

对于一个父进程,fork 的返回值是创建的子进程的进程描述符(process identifier, PID);

对于子进程,返回值是 0;

如果子进程创建失败(由于内存不足等原因),返回值-1。

实例演示

以一段 C 程序为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
printf("hello world (pid:%d)\n", (int) getpid());
int rc = fork(); // 返回值其实是 pid_t 类型
if (rc < 0) { // fork failed
fprintf(stderr, "fork failed\n");
} else if (rc == 0) { // child process
printf("hello, I am child (pid:%d) \n", (int) getpid());
} else { // parent process
printf("hello, I am parent of %d (pid:%d)\n", rc, (int) getpid());
}
return 0;
}

根据进程调度的不同,可能有以下两种输出结果:(当然 pid 也大概率不一致)

1
2
3
4
5
6
7
hello world (pid:285)
hello, I am parent of 286 (pid:285)
hello, I am child (pid:286)
// another possible result
hello world (pid:285)
hello, I am child (pid:286)
hello, I am parent of 286 (pid:285)

观察发现,hello world 只在父进程打印了,而没有在子进程中进行打印

例题

  1. 在 UNIX 系统下执行以下程序,最多可再产生几个进程?

    1
    2
    3
    4
    5
    main() {
    fork(); // PC is here
    fork();
    fork();
    }

    ANS: 7

  2. 以下程序一种可能的输出(设最开始的进程的 PID 为 1000)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include "stdio.h"
    #include "sys/types.h"
    #include "unistd.h"
    int main() {
    pid_t pid1;
    pid_t pid2;
    pid1 = fork();
    pid2 = fork();
    printf("pid1:%d, pid2:%d\n", pid1, pid2);
    }

    // possible result
    pid1:1001, pid2:1002 (1000 进程的输出)
    pid1:0, pid2:1003 (1001 进程的输出)
    pid1:0, pid2:0 (1003 进程的输出)
    pid1:1001, pid2:0 (1002 进程的输出)

    解析:画出树形图比较方便(Linux 中的进程也是按照树的结构组织的) 此外注意,1003 进程的 pid1 为 0,1002 进程的 pid 为 1001,是从它们各自的父进程复制而来的

Ref:

  1. Linux Programmer's Manual: man fork man vfork
  2. 【linux】linux中fork()详解(实例讲解)|fork的运行机制_bandaoyu的博客-CSDN博客_linux fork

fork() 小记
https://balddemian.github.io/Fork-Glimpse/
作者
Peiyang He
发布于
2023年2月21日
许可协议