美文网首页LinuxLinux学习之路
APUE读书笔记-09进程关系(3)

APUE读书笔记-09进程关系(3)

作者: QuietHeart | 来源:发表于2020-05-26 08:35 被阅读0次

    5、Session

    一个session是一个或者多个进程组的集合。参考资料中给出了一个简单的图来表示这个意思。

    这里不给出图了,叙述一下图中描述的情况:
    有一个session,session中有三个进程组。第一个进程组中有一个login shell进程;第二个进程组中有两个进程:proc1,proc2;第三个进程组中有三个进程:proc3,proc4,proc5。

    在个进程组中的进程,一般都是通过shell管道的方式来产生的,上面叙述的图中的后两个进程组是通过如下的命令产生的:

    proc1 | proc2 &
    proc3 | proc4 | proc5
    

    一个进程是通过调用函数setsid来建立一个会话(session)的。这个函数如下:

    #include <unistd.h>
    pid_t setsid(void);
    

    这个函数正确的时候返回进程组id,错误的时候返回1(其值实际为-1)。

    如果调用这个函数的进程不是一个进程组leader,那么这个函数创建一个新的session,这时候有如下三个事情发生:

    1. 进程变成这个新session的session leader(一个session leader就是创建这个session的进程),并且这个进程成为这个新的session中的唯一的进程。
    2. 进程变成一个新的进程组的leader。这个新的进程组id就是这个调用setsid函数的进程的进程id。
    3. 进程没有controlling terminal(控制终端)。我们将在下一节讨论控制终端。如果再进程调用setsid函数之前这个进程具有了一个控制终端,那么和那个控制终端的联系会被断开。

    如果调用进程已经是一个进程组的leader了,那么这个函数这个函数会返回一个错误。为了确保不会发生这种情况,一般的方法是调用fork创建一个子进程,然后让父进程终止,子进程继续;这样我们可以保证子进程不是一个进程组leader,因为子进程会自动继承父进程的进程组id,但是子进程的进程号却是新产生的(和父进程不同)(所以子进程的pid就不等于父进程的pid,所以也不等于其进程组的组id了,因为组id和组leader的pid相等).

    Single UNIX Specification只说了"session leader",并没有和进程ID和进程组ID类似的"session ID"的说法。很显然,一个session leader就是一个单个的进程,所以我们说到 session ID的时候,就认为那是这个session的session leader的进程pid。session ID的概念是在SVR4中引入的。BSD体系的系统没有支持这个概念,但是已经被更新包含了这个相关的东西。 getsid函数返回一个进程的session leader的的进程组id。getsid函数在Single UNIX Specification中被作为XSI扩展包含进去了。

    Solaris和Single UNIX Specification差不多,它尽量避免使用"session id"的概念,它采用的说法是"process group ID of the session leader".这两种说法是相等的,一个session 的leader一直都是一个process group的leader。

    获取session id的函数:

    #include <unistd.h>
    pid_t getsid(pid_t pid);
    

    如果正确会返回session leader的process group ID,错误的时候返回1(其值实际为-1)。

    如果pid是0,那么getsid返回调用进程的session的进程组id。由于某些安全性的因素,有些实现可能会在pid参数和进程id不属于同一个session的情况下限制调用进程获取相应的"session id"。

    译者注

    原文参考

    参考: APUE2/ch09lev1sec5.html

    6、控制终端

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

    1. 会话可以有一个单个的控制终端。这个控制终端一般都是我们登陆时候的终端设备(在终端登陆的情况下),或者是一个伪终端设备(在网络登陆的情况下)。
    2. 建立到控制终端连接的会话leader被称作控制进程。
    3. 在一个会话中的进程组可以被分成一个单一的前台进程组,以及一个或者多个后台进程组。
    4. 如果一个session有一个控制终端,那么它有一个单一的前台进程组,这个session(session就是会话)其他的进程组是后台进程组。
    5. 当我们键入终端的中断键(一般都是DELETE或者Control-C)的时候,会发送给所有在前台进程组中的进程一个中断信号。
    6. 当我们敲入终端的quit键(一般是Control-backslash)的时候,这会导致一个quit信号发送给所有前台进程组的进程。
    7. 如果一个modem(或者网络)的连接断开被终端的接口检测到了,那么会给控制进程(session leader)发送一个hang-up信号。

    参考资料给出了一个图描述了这个叙述。这里不给出原图形了,简单总结原图的意思就是:

    1. controlling terminal在检测到modem disconnect之类的情况的时候会给login shell(也是后台进程组中的进程,也是session leader,也是控制进程)发送hang-up信号。
    2. 终端输入或者终端发起的信号会发送给session中的前台进程组。
    3. 另外,一个session中还有可能存在其他的后台进程组。

    一般来说,我们不用担心控制终端,因为在我们登陆进去的时候它会自动被建立。

    POSIX.1把分配控制终端机制留给了各自实现。

    从UNIX System V继承过来的系统,会在session leader打开第一个没有和session建立联系的终端设备的时候分配一个控制终端.当然这假设session leader调用的open没有指定O_NOCTTY标志。

    基于BSD的系统会在session leader调用ioctl(有一个TIOCSCTTY请求参数,第三个参数是空指针)的时候给一个session分配一个控制终端。在调用之前,session不能已经有了controlling terminal(否则调用不成功).一般来说,这个ioctl调用后面需要接着一个setsid调用,这个调用保证进程是一个没有控制终端的session leader.在BSD系列的系统中,POSIX.1中open的O_NOCTTY标记并没有使用,除非是要和其他系统相互兼容的时候。

    有时候一个程序想要和controlling terminal进行交互,并且不考虑标准输入输出是否被重新定向了。程序用来确保自己是要和controlling terminal进行交互的方法是通过打开/dev/tty文件.这个特殊文件在内核中和controlling terminal是同义的。一般来说,如果程序没有controlling terminal,那么打开这个设备文件会失败。
    一个经典的例子是getpass函数,这个函数读取密码(这时候terminal 的echo是关闭的).这个函数被crypt程序调用,可以在管道中使用。例如:

    crypt < salaries | lpr
    

    解密salaries文件然后通过管道输出到打印池。因为crypt从标准输入读取输入文件,不用使用标准输入输入密码。并且,crypt程序每次运行的时候,需要输入加密的密码,这样我们就不用将密码保存在文件中了(保存在文件中有安全隐患)。

    有一些已知的方法将crypt使用的encoding给break,这里不说了。

    译者注

    原文参考

    参考: APUE2/ch09lev1sec6.html

    相关文章

      网友评论

        本文标题:APUE读书笔记-09进程关系(3)

        本文链接:https://www.haomeiwen.com/subject/quplohtx.html