上一篇文章完成了一个有关进程扇和进程组的练习,不过在结尾处留了一个小坑,本篇也不打算继续填坑,毕竟这是作为练习留在篇末的。

1. 目标

本篇希望利用进程链完成一个小实验,希望达到图 1 中的效果,即将进程 0 (父进程)和进程 2 设置成一组,假设为组 1,将进程 1 和 进程 3 设置成另一个组,假设为组 2. 另外,我们希望进程 0 和进程 1 分别是这两个组的组长。


66-进程组(实验二)_getpgid


图1 将进程链分成两组


2. 思路

  • 首先,利用前面的知识,创建包含 4 个进程的进程链。
  • 创建进程组 1,即将进程 0 设置为组长;再将进程 2 加入组 1.
  • 创建进程组 2,即将进程 1 设置为组长;再将进程 3 加入组 2.

创建进程组和将某个进程划分到一个进程组在上节已经讲过,这里不在赘述。

3. 程序清单

3.1 代码

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main() {
int pid, i;
int group1, group2;

setpgid(getpid(), getpid());
group1 = getpgid(getpid());


for (i = 0; i < 3; ++i) {
pid = fork();
if (pid > 0) {
// father
if (i == 0) {
setpgid(pid, pid);
group2 = getpgid(pid);
}
else if (i == 1) {
setpgid(pid, group1);
}
else if (i == 2) {
setpgid(pid, group2);
}
break;
}
else if (pid == 0) {
// child
if (i == 0) {
setpgid(getpid(), getpid());
group2 = getpgid(getpid());
}
else if (i == 1) {
setpgid(getpid(), group1);
}
else if (i == 2) {
setpgid(getpid(), group2);
}
}
else if (pid < 0) {
perror("fork");
return -1;
}
}

printf("进程 %d, pid: %d -> ppid: %d, pgid: [%d], (%s)\n", i, getpid(), getppid(), getpgid(getpid()), strerror(errno));
while(1) sleep(1);
return 0;
}

3.2 编译与运行

  • 编译并运行
$ gcc ps_swing_v1.c -o ps_swing_v1
$ ./ps_swing_v1
  • 运行结果


66-进程组(实验二)_getpgid_02


图2 运行结果


从图 2 中可以观察出,我们的程序已经运行成功了。其中进程 0 和进程 2 位于组 5569,组长是进程 0;而进程 1 和进程 3 位于组 5570,组长是进程 1.

细心的同学如果读完本篇,相信上一篇的 bug 你也可以自己动手解决了。

4. 总结

  • 掌握设置进程组的方法
  • 理解为什么要同时在父子里进程里设置进程组

练习:尝试使用命令​​kill​​​将组 1 杀死,再使用 ​​ps ajx​​ 观察结果。