码迷,mamicode.com
首页 > 系统相关 > 详细

apue第九章 孤儿进程组例子

时间:2019-04-19 00:43:12      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:tst   get   异常   std   self   例子   tpi   终止进程   原因   

 

1. 为什么会有孤儿进程组的概念,APUE没写清楚,但是GNU有规定:

孤儿进程组不可以获得终端,这是为了保证控制进程死掉后他的终端可以安全分配给新session。posix要求向新孤儿进程组中停止状态的进程(也有说是孤儿进程组里所有进程)发送SIGHUP(挂起)信号和SIGCONT(继续)信号。首先处理SIGHUP信号,系统默认处理是终止进程,然而也可以另行处理这样进程会继续执行,但任不可以再获得终端。

2. 书本代码示例apue.3e/relation/orphan3.c较费解

#include "apue.h"
#include <errno.h>

static void
sig_hup(int signo)
{
    printf("SIGHUP received, pid = %ld\n", (long)getpid());
}

static void
pr_ids(char *name)
{
    printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
        name, (long)getpid(), (long)getppid(), (long)getpgrp(),
        (long)tcgetpgrp(STDIN_FILENO));
    fflush(stdout);
}

int
main(void)
{
    char    c;
    pid_t    pid;

    pr_ids("parent");
    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid > 0) {    /* parent */
        sleep(5);        /* sleep to let child stop itself */
    } else {            /* child */
        pr_ids("child");
        signal(SIGHUP, sig_hup);    /* establish signal handler */
        kill(getpid(), SIGTSTP);    /* stop ourself */
        pr_ids("child");    /* prints only if we‘re continued */
        if (read(STDIN_FILENO, &c, 1) != 1)
            printf("read error %d on controlling TTY\n", errno);
    }
    exit(0);
}

这里,father等待5秒后狗带,child运行结果如下:

[karenyin@host relation]$ ./orphan3
parent: pid = 15877, ppid = 15811, pgrp = 15877, tpgrp = 15877 // father是组长,也是前台进程组ID,father的father是shell,shell pid=15811
child: pid = 15878, ppid = 15877, pgrp = 15877, tpgrp = 15877  // child是组员,当前这个进程组占据了终端。结果输出在这里停了几秒,然后才打印下一句“SIGHUP received”
[karenyin@host relation]$ SIGHUP received, pid = 15878         // 进程组先退出终端,然后又在终端打印SIGHUP
child: pid = 15878, ppid = 1, pgrp = 15877, tpgrp = 15811      // 前台进程组已经不是father了,说明终端又交给了shell
read error 5 on controlling TTY                         // 这里是child试图读标准输入read(STDIN_FILENO, &c, 1),触发了异常。
^C                                     // child似乎没有走到exit(0)

原因分析如下:

1. kill(15878, SIGTSTP)并不是要child杀死自己,而是暂停前台作业。

技术图片

2. father自然死亡后,child成为孤儿进程,被init收养,因此ppid=1。

 child也成为进程组15877也成为孤儿进程组,因此收到SIGHUP信号(之后还会收到SIGCONT信号,表示继续)。

3. 子进程处理SIGHUP信号的时候,已经是孤儿进程组成员了,没有权限刷到标准输出,为什么成功打印了“SIGHUP received, pid = 15878”呢?同样的疑惑,为什么child能在终端打印“read error %d on controlling TTY\n”呢?关于这个疑问其实apue也有写,POSIX.1只对读控制终端作出限制。

技术图片

 所以说,gnu对孤儿进程组的定义里access一词的意思是“读”,孤儿进程组成员试图读取控制终端时才抛EIO,对写终端未做规定。

技术图片

小结

这个故事说明,像W.Richard Stevens这种处在技术书籍第一列队的作者,写书不会含糊跳过的,因此一种省时间的看这位老哥的书的方式是,在书本里找答案,不要自信跳过。

apue第九章 孤儿进程组例子

标签:tst   get   异常   std   self   例子   tpi   终止进程   原因   

原文地址:https://www.cnblogs.com/yinkw/p/apue.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!