Unix进程间关系

终端登录  

  在用户使用终端登录Unix操作系统过程中,操作系统首先进行自引导,由内核创建初始化进程(进程ID为1),初始化进程使操作系统进入多用户状态。初始化进程读取/etc/tty文件中的内容,为每一个终端设备新建一个子进程,并执行getty程序。getty程序为当前终端打开文件描述符0、1、2至终端设备,并初始化环境变量列表,执行login程序,等待用户登录。如图1所示。

图1.  终端登录调用login后状态

  用户登录成功后,login程序根据所登录的用户对进程环境变量做出调整。login程序调用setgid及setuid系统函数,运行login shell,加载引导文件(.profile文件)。完整的终端登录过程至此结束。如图2所示。

图2.  终端登录完成各种设置后状态

 

 进程组:

  每一个进程组都有一个Leader,即该进程组的创建者。使用setpgid函数可以将调用进程的子进程或调用进程本身加入到指定进程组中,若子进程调用了exec函数,则父进程无法为该子进程指定进程组。setpgid函数原型为

#include <unistd.h>
int setpgid(pid_t pid, pid_t gid);

当gid与pid相等时时,pid成为进程组的leader。当参数为0时,将使用当前进程值(pid、gid)代替值为0的参数。

 

会话(session):

  一个会话可以包含多个进程组,但多个进程组之中最多仅能有一个前台进程组,其他进程组均为后台进程组。使用setsid函数可以创建新会话,当前进程为新会话的创建者(leader),同时,当前进程新建了一个进程组,并作为进程组leader。新建会话并不包含控制终端,如果创建会话前该进程包含控制终端,则会话创建后控制终端被连接被断开。在Unix中,实际上并不存在会话ID的定义,当需要获取会话ID时,可以通过获取会话leader的进程组ID来达到同样目的。

 

控制终端(controlling terminal):

  控制终端与会话相连接,用户可以通过控制终端与进程进行交互。通常控制终端由登录时自动建立。如果会话具有控制终端,则该会话可以有一个前台进程组与多个后台进程组。如果后台进程需要与控制终端进行交互,可以通过/dev/tty文件绕过前台进程。

  当需要指定或获取前台进程组时,可使用tcsetpgrp函数与tcgetpgrp函数。使用tcgetsid函数可以通过控制终端获得当前会话leader进程组ID(即会话ID),若当前会话没有控制终端,则函数调用失败,返回-1。

 

孤儿进程组(orphan process group):

  当会话中的某一个进程组中任一进程与其父进程处于同一进程组,或父进程不在该会话内,则该进程组被称为孤儿进程(orphan process group)。POSIX。1标准要求向新建的孤儿进程组中中断(stop)的进程发送挂断信号(SIGHUP),然后发送一个继续信号(SIGCONT)。

 

作业控制(jobs control):

  作业控制需要得到shell、与内核的支持。内核需要支持建立作业控制信号,提供终端设备驱动对作业控制的支持。一般来说,C Shell与Bourne-again Shell支持作业控制;Bourne Shell不支持作业控制。

  当后台进程组请求从终端中读取交互数据时,终端向后台进程组发送SIGTTIN信号,该信号默认操作为中断后台进程操作,我们可以通过终端操作使后台进程调往前台运行(fg命令),使该进程能够读取终端中的交互数据。

  当后台进程组请求向终端中输出数据时,终端是否显示数据是可以选择的。我们可以使用stty命令更改这个选择。当我们不允许后台进程向终端中输出数据时,后台终端遇到输出数据代码会出现阻塞。直到后台进程转为前台进程,并输出相关数据为止。应当尽量避免后台进程组通过/dev/tty与控制终端交互。因为其结果是依赖与具体实现的。

  在Bourne Shell中,当使用管道控制进程组时,管道中最后一个进程为进程组的leadder,其余进程均为该进程的子进程。在Bourne-again Shell中,shell进程为管道中所有进程的父进程。

posted @ 2012-08-16 16:36  o0慢节奏0o  阅读(738)  评论(0编辑  收藏  举报