本章话题主要关注进程间关系。比如有关进程组、进程组组长、会话、前台进程组等这些概念。设计进程扇和进程链的概念,是为了方便描述进程间关系以及完成相关的实验。

1. 进程扇

如果有一个进程,它生成了若干个进程,这若干个进程之间都是兄弟进程,就把这种关系称为进程扇结构,这一系列进程就是一个进程扇。如图 1 所示。


63-进程扇与进程链_fork


图1 进程扇


1.1 进程扇构造代码

// ps_swing.c
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
int pid, i = 4;

while(i--) {
pid = fork();
if (pid == 0) {
// 如果是子进程,就不能继续循环了。
// 按照进程扇的定义,子进程是没有子进程的。
break;
}
else if (pid < 0) {
perror("fork");
return -1;
}
}

printf("pid: %d -> ppid: %d\n", getpid(), getppid());
while(1) sleep(1);
return 0;
}

1.2 编译与运行

  • 编译与运行
$ gcc ps_swing.c -o ps_swing
$ ./ps_swing
  • 运行结果


63-进程扇与进程链_fork_02


图2 进程扇的构造


  • 使用​​pstree -ap​​ 命令查看进程间关系


63-进程扇与进程链_进程链_03


图3 查看进程间关系


从图 3 可以看出 ps_swing 这几个进程符合进程扇的定义。

2. 进程链

如果某个进程生成了一个子进程,它的子进程又生成了一个子进程,直到最后一个子进程不再产生新的子进程,那么这一系列进程被称为进程链。如图 4 所示。


63-进程扇与进程链_fork_04


图4 进程链


2.1 进程链构造代码

// ps_link.c
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
int pid, i = 4;


while(i--) {
pid = fork();
if (pid > 0) {
// 如果是父进程,产生了子进程后就必须退出循环。
// 因为按照进程链定义,一个父进程只能产生一个子进程。
break;
}
else if (pid < 0) {
perror("fork");
return -1;
}
}

printf("pid: %d -> ppid: %d\n", getpid(), getppid());
while(1) sleep(1);
return 0;
}

2.2 编译与运行

  • 编译与运行
$ gcc ps_link.c -o ps_link
$ ./ps_link
  • 运行结果


63-进程扇与进程链_进程链_05


图5 进程链的构造


  • 使用​​pstree -ap​​ 命令查看进程间关系


63-进程扇与进程链_fork_06


图6 查看进程间关系


从图 6 中可以看到,6934、6935、6936、6937 和 6938 这 5 个进程构成了一种链式关系。

3. 总结

  • 掌握进程扇和进程链的基本概念
  • 掌握进程扇和进程链的构造方法

练习:使用 ​​pstree​​ 命令查看进程扇和进程链的结构,并显示进程 ID、进程组 ID。