进程组 会话组 控制终端

1. 进程组

每个进程除了有一个进程ID之外,还有一个进程组。进程组是一个或多个进程的集合。它们与同一作业相关联,可以接受来自同一终端的各种信号。每个进程组都有唯一的进程组ID。函数getpgrp可以得到进程的进程组ID。

pid_t getpgrp(void);

每个进程组都可以有一个组长进程。组长进程的标识是,其进程组ID等于进程ID。组长进程可以创建一个进程组,创建该组中的进程,然后终止。只要在某个进程组中有一个进程存在,则该进程组就存在,与其组成进程是否终止无关。进程组的最后一个进程可以终止,或者转移到另一个进程组。

进程可以调用setpgid来加入一个现有的组或者一个新进程组。

int setpgid(pid_t pid, pid_t pgid);

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

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

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

2. 会话

会话(session)是一个或多个进程组的集合。进程调用setsid函数建立新会话。

pid_t setsid(void);

如果调用此函数的进程不是一个进程组的组长,则此函数会创建一个新会话,结果如下:

1). 该进程变成新会话首进程(session leader)。会话首进程是创建该会话的进程。

2). 该进程成为一个新进程组的组长进程。新进程组ID是该调用进程的进程ID。

3). 该进程没有控制终端。如果在调用setsid之前该进程就有一个控制终端,那么这种联系也会被中断。

如果该调用进程已经是一个进程组的组长,则此函数返回出错。为了保证不会发生这种情况,通常先调用fork,然后使其父进程终止,而子进程则继续。

函数getsid返回会话首进程的进程组ID。此函数是Single UNIX Specification的XSI扩展。

pid_t getsid(pid_t pid);

如果pid是0,返回调用进程的会话首进程的进程组ID。如果pid并不属于调用者所在的会话,那么调用者就不能得到该会话首进程的进程组ID。

3. 控制终端

会话和进程组有一些特性:

1). 一个会话可以有一个控制终端(controlling terminal)。

2). 建立与控制终端连接的会话首进程被称为控制进程(controlling process)。

3). 一个会话中的几个进程组可被分成一个前台进程组(forkground process group)和几个后台进程组(background process group)。

4). 如果一个会话有一个控制终端,则它有一个前台进程组。

5). 无论何时键入终端的中断键(DELETE或Ctrl+C),就会将中断信号发送给前台进程组的所有进程。

6). 无论何时键入终端的退出键(Ctrl+\),就会将退出信号发送给前台进程组的所有进程。

7). 如果终端检测到调制解调器(或网络)已经断开连接,则将挂断信号发送给控制进程(会话首进程)。

现在,需要有一种方法通知哪个进程组是前台进程组,这样终端设备驱动程序就能了解将终端输入和终端产生的信号送到何处。

pid_t tcgetpgrp(int filedes);

pid_t tcsetpgrp(int filedes, pid_t pgrpid);

函数tcgetpgrp返回前台进程组的进程组ID,该前台进程组与在filedes上打开的终端相关联;如果进程有一个控制终端,则该进程可以调用tcsetpgrp将前台进程组ID设置为pgrpid,pgrpid的值应该是在同一会话中的一个进程组的ID,filedes必须引用该会话的控制终端。

Single UNIX Specification的XSI扩展,给出了控制TTY的文件描述符。

pid_t tcgetsid(int filedes);

需要管理控制终端的应用程序可以调用该函数识别出控制终端的会话首进程的会话ID(会话首进程的进程组ID)。

补充:

1.通过ps和pstree可以看到,进程之间的管理主要是建立在父子进程的基础上

2.当会话组进程结束时,会话组进程下的子孙进程也会被关闭

3当父进程退出时,子进程的父进程被修改为init(1),当该会话组控制进程退出时,当前的子进程不退出,但sid还是之前的sid

4.当父进程退出,子进程调用setsid时,子进程以自己的pid为sid和gid

posted @ 2013-02-22 13:36  only_eVonne  阅读(1414)  评论(0编辑  收藏  举报