进程关系之进程组

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

进程组是一个或多个进程的集合。通常,它们与同一作业相关联,可以接收来自同一终端的各种信号。每个进程组有一个唯一的进程组ID。进程组ID类似于进程ID——它是一个正整数,并可存放在pid_t数据类型中。函数getpgrp返回调用进程的进程组ID

#include <unistd.h>
pid_t getpgrp(void);
返回值:调用进程的进程组ID

在早期BSD派生的系统中,该函数的参数是pid,返回该进程的进程组ID。Single UNIX Specification将getpgid函数定义为XSI扩展,它模仿了此中运行行为。

#include <unistd.h>
pid_t getpgid(pid_t pid);
返回值:若成功则返回进程组ID,若出错则返回-1

若pid为0,则返回调用进程的进程组ID,于是,getpgid(0);等价于getpgrp();

每个进程组都可以有一个组长进程。组长进程的标识是,其进程组ID等于其进程ID

组长进程可以创建一个进程组,创建该组中的进程,然后终止。只要在某个进程组中有一个进程存在,则该进程组就存在,这与其组长是否终止无关。从进程组创建开始到其中最后一个进程离开为止的时间区间称为进程组的生存期。进程组中的最后一个进程可以终止,或者转移到另一个进程组。

进程可以通过调用setpgid来加入一个现有的组或者创建一个新进程组

#include <unistd.h>
int setpgid(pid_t pid, pid_t pgid);
返回值:若成功则返回0,若出错则返回-1

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

一个进程只能为自己或它的子进程设置进程组ID。在它的子进程调用了exec函数之一后,它就不再能改变该子进程的进程组ID。

在大多数作业控制shell中,在fork之后调用此函数,使父进程设置其子进程的进程组ID,并且使子进程设置其自己的进程组ID。这两个调用中有一个是冗余的。如果不这样做的话,那么fork之后,由于父、子进程运行先后次序的不确定,会造成在一段时间内(父、子进程中只运行了其中一个)子进程组成员身份的不确定(取决于哪个进程首先执行),这就产生了竞争条件。

 

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

原文地址:https://www.cnblogs.com/nufangrensheng/p/3513323.html