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

孤儿进程组不可以获得终端,这是为了保证控制进程死掉后他的终端可以安全分配给新session。posix要求向新孤儿进程组中停止状态的进程(GNU说是给孤儿进程组里所有进程发消息,而APUE中文版说是给停止状态的进程发消息)发送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()) < ) {
err_sys("fork error");
} else if (pid > ) { /* parent */
sleep(); /* 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, ) != )
printf("read error %d on controlling TTY\n", errno);
}
exit();
}

上面代码,father等待5秒后狗带,child运行结果如下:

[karenyin@host relation]$ ./orphan3
parent: pid = , ppid = , pgrp = , tpgrp = 15877 // father是组长,也是前台进程组ID,father的father是shell,shell pid=15811
child: pid = , ppid = , pgrp = , tpgrp = 15877 // child是组员,当前这个进程组占据了终端。结果输出在这里停了几秒,然后才打印下一句“SIGHUP received”
[karenyin@host relation]$ SIGHUP received, pid = 15878 // 进程组先退出终端,然后又在终端打印SIGHUP
child: pid = , ppid = , pgrp = , tpgrp = 15811 // 前台进程组已经不是father了,说明终端又交给了shell
read error 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第九章之孤儿进程组的更多相关文章

  1. 第九章 广播和本地组播(IGMP和MLD)

    距离项目开启已经过去了一段时间,这段时间内自己学习的内容也算挺多的,但是也较容易遗忘,之后应该在空余的时间内多翻翻博客,更加清楚传统计算机网络的运作. 由于51要出去玩,更要好好利用好最近的时间.完成 ...

  2. 《UNIX环境高级编程》(APUE) 笔记第九章 - 进程关系

    9 - 进程关系 GitHub 地址 1. 进程组 每个进程除了有一个 进程 ID 外,还属于一个 进程组 .进程组是一个或多个进程的 集合 ,通常,它们是在同一作业中结合起来的,同一进程组中的各进程 ...

  3. 进程组与会话 Linux Process Groups and Sessions

    在类Unix系统中,用户通常会跟各种相关的进程打交道.虽然在登录的时候只有一个终端进程(用户对应的登录shell ,通过这个shell启动各种程序和服务),但通常不久以后就会产生许多相关的进程,例如进 ...

  4. apue学习笔记(第九章 进程关系)

    本章将详细地说明进程组以及POSIX.1引入的会话的概念.还将介绍登录shell和所有从登录shell启动的进程之间的关系 终端登录 BSD终端登录.系统管理者创建通常名为/etc/ttys的文件,其 ...

  5. APUE 2 - 进程组(process group) 会话(session) job

    进程组(process group) 进程组顾名思义是指一个或多个进程的集合.他们通常与同一个job(可以从同一个终端接收信号)相关联.每个进程组拥有一个唯一的Process Group Id.可以使 ...

  6. 【APUE】孤儿进程与僵死进程

    基本概念: 在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一个 进程 ...

  7. 重读APUE(8)-进程、进程组、会话

    进程: 是系统中一段程序执行的实体,也是资源分配和调度的基本单位: 进程组: 为了方便管理多个进程,可以将多个进程加入到一个进程组内: 每个进程都属于一个进程组,但是同一个进程组内可以有多个进程: 每 ...

  8. Laxcus大数据管理系统2.0(11)- 第九章 容错

    第九章 容错 在当前,由于集群庞大的组织体系和复杂性,以及用户普遍要求低成本硬件,使得集群在运行过程中发生的错误概率,远远高于单一且性能稳定的小型机服务器,并且集群在运行过程中几乎是不允许停止的,这就 ...

  9. wait、waitpid 僵尸进程 孤儿进程

    man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...

随机推荐

  1. TensorFlow:检查显卡支持哪个版本的CUDA

    最近想学习TensorFlow深度学习编程,然后就开始查这方面的信息. 第0步是安装环境,配置环境. 首先到TensorFlow的官网查看在Windows上安装的条件和步骤. 可以仅仅安装CPU版本的 ...

  2. 浅谈C#语言中的各种数据类型,与数据类型之间的转换

    什么是数据类型? 数据类型,百度百科是这样解释的:数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作.这样的解释对于一个初学者来说未必太过于深奥. 简单点说,数据类型就是不同长度的 ...

  3. WebView 判断放大缩小操作

    using Android.App; using Android.Widget; using Android.OS; using Android.Content; using Android.Runt ...

  4. Day 23 面向对象(二)

    一.对象独有的名称空间 在产生对象时就赋初值 class Student: def __init__(self,name,sex): self.name = name self.sex = sex # ...

  5. 同一台电脑配置多个JBoss

    在jboss中找到对应的文件,修改对应文件端口可解决两个以上jboss的端口冲突问题 不同的jboss修改的端口要区别开来,本例所用jboss版本为JBoss4.2.2.GA 文件端口: 8083,1 ...

  6. 解决spyder、Jupyter Notebook 打不开

    参考: https://blog.csdn.net/lanchunhui/article/details/72891918 https://stackoverflow.com/questions/49 ...

  7. http摘要认证

    摘要认证步骤:      1. 客户端访问一个受http摘要认证保护的资源.      2. 服务器返回401状态以及nonce等信息,要求客户端进行认证. HTTP/1.1 401 Unauthor ...

  8. 《重构-改善既有代码的设计》学习笔记---Replace Temp with Query(以查询取代临时变量)

    临时变量的问题在于: 它们是暂时的,而且只能在所属函数内使用.由于临时变量只在所属函数内可见,所以,如果很多地方都在用这个临时变量,就会驱使你写出更长的函数.如果把临时变量替换为一个查询,那么其他函数 ...

  9. linux kernel mini2440 start.S head-common.S 部分注释

    内核版本:2.6.32.2(mini2440光盘源码) github地址:https://github.com/guanglun/mini2440_uboot_linux (for_len分支 htt ...

  10. 【Algorithm】字符串编辑距离(Levenshtein距离)C++算法实现

    算法实现比较简单,但算法原理不明白,有空了再研究一下. unsigned LevenshteinDistance(const string& s1, const string& s2) ...