apue第九章 孤儿进程组例子
Posted yinkw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了apue第九章 孤儿进程组例子相关的知识,希望对你有一定的参考价值。
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 ", (long)getpid()); } static void pr_ids(char *name) { printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld ", 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 ", errno); } exit(0); }
这里,father等待5秒后狗带,child运行结果如下:
[[email protected] 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” [[email protected] 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 ”呢?关于这个疑问其实apue也有写,POSIX.1只对读控制终端作出限制。
所以说,gnu对孤儿进程组的定义里access一词的意思是“读”,孤儿进程组成员试图读取控制终端时才抛EIO,对写终端未做规定。
小结
这个故事说明,像W.Richard Stevens这种处在技术书籍第一列队的作者,写书不会含糊跳过的,因此一种省时间的看这位老哥的书的方式是,在书本里找答案,不要自信跳过。
以上是关于apue第九章 孤儿进程组例子的主要内容,如果未能解决你的问题,请参考以下文章