进程组

每个进程除了有一个进程ID之外,还属于一个进程组

进程组是一个或多个进程的集合。每个进程组有一个唯一的进程组ID,进程组ID类似于进程ID。

获取进程组ID

在早期的UNIX系统中使用以下函数查看进程组ID:

#include <unistd.h>

pid_t getpgid(pid_t pid);	//若成功返回进程组ID,出错返回-1

到了现在一般用以下函数:

#include <unistd.h>

pid_t getpgrp(void);	//若成功返回调用进程的进程组ID

如果getpgid函数中的pid参数为0,其实也就等同于getpgrp

组长进程

国不可一日无君,群不可一日无群主
							———— 沃兹基.硕德

每个进程组都可以有一个组长进程其进程ID等于其进程组ID

组长进程可以创建一个进程组,创建该组中的进程,然后终止。只要在某个进程组中有一个进程存在,则该进程组就存在,这与其组长进程是否终止无关。

设置进程组

进程可以通过以下函数来加入一个现有的组或者创建一个新进程组

#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);		//若成功则返回0,出错返回-1

setpgid函数将pid进程的进程组设置为pgid。如果这两个参数相同,则pid指定的进程成为进程组组长
另外,如果pid = 0,则使用调用者的进程ID;如果pgid = 0,则由pid指定的进程ID作为进程组ID,成为组长。

每个进程只能为自己或者其子进程设置进程组ID。但是!子进程调用exec函数之后,他就不能改变该子进程的进程组ID

在大多数作业控制shell中,在fork之后调用此函数,使父进程设置其子进程的进程组ID,并且使子进程设置其自己的进程组ID

这里有个问题:为什么要设置两次,不麻烦么?

还记得我们在进程一文中提到的。由于内核进程调度原因,父子进程调度顺序未知的问题么

没错,只有这样才能够保证子进程被正确的设置了进程组。

孤儿进程组

在POSIX.1中定义了孤儿进程组。

该进程组的每个成员的父进程要么是该组的成员,要么在其他会话中

所以说,下图的进程组1就不是孤儿进程组

因为进程组1中父进程的父进程不属于进程组1且不在会话2中。

而进程组2就是父进程,因为它的每个进程的父进程要么在本组中,要么在其他会话中。

孤儿进程组的特性

如果一个进程组包含一个或一个以上的停止的进程,当该进程组成为孤儿进程组,每个进程都会收到SIGHUP信号,紧接着又会收到SIGCONT信号。

参考文献

[1]UNIX环境高级编程(第二版)