进程组
进程组是一个或多个进程的集合,通常它们与同一任务相关联,它能从同一终端接收信号。每个进程组有唯一的进程组ID。进程组ID和进程ID很相似:它们都是正整数并且能被存到pid_t类型中。函数getpgrp可以返回调用进程的进程组ID:
|
旧的BSD衍生系统,getpgrp函数需要一个pid参数,之后才能返回该进程的组ID。Single UNIX Specification定义的getpgid函数做为XSI扩展,模仿了这个行为。
|
如果pid是0(零)调用进程的组ID被返回。因此,
getpgid(0);
等于
getpgrp();
每个进程组可以有一个进程组长(process group leader),在组中建立进程和结束进程。进程组长的表标是,其进程组ID等于其进程ID。只要进程组中还有一个进程存在,无论它是否是进程组长,进程组都会存在。进程组的生命周期起始于进程组的建立,结束于进程组中最后一个进程离开进程组。最后一个进程的离开,可以是进程结束,也可以是加入到其它进程组中。
一个进程加到一个存在的进程组中或创建一个新的进程组,可能通过调用setpgid函数。(之后还会介绍setsid,它也可以创建进程组)
|
这个函数设置进程ID为pid的进程组ID为pgid。如果两个参数相等,那么pid会成为进程组头(process group leader)。如果pid是0(零),那么使用调用者的pid。同样,如果pgid是0(零),pid做为进程组ID。
一个进程只能设置它的进程组ID是它自己的PID或者是它子进程的PID。另外,在一个子进程调用过exec函数某个版本后,它不能改变该子进程的进程组ID。(Further more, it can’t change the process group ID of one of its children after that child has called one of the exec functions.)
在多数的任务控制shell中,这个函数在fork后调用,在父进程中为子进程设置进程组ID,在子进程中为自己设置进程组ID。这两个调用其中之一是冗余的,但是通过这种双保险,我们可以保证在父进程或子进程认为已经把子进程放入自己的进程组之前,已经把子进程被放到自己的进程组中(One of these calls is redundant, but by doing both, we are guaranteed that the child is placed into its own process group before either process assumes that this has happened)。如果不这么做,将会产生竞争条件,因为子进程的进程组成员将依赖于哪个进程先执行。