1. 程式人生 > >apue第九章 孤兒進程組例子

apue第九章 孤兒進程組例子

孤兒進程 amp rec getpid sel 進程 err inf kill

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運行結果如下:

[[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\n”呢?關於這個疑問其實apue也有寫,POSIX.1只對讀控制終端作出限制。

技術分享圖片

所以說,gnu對孤兒進程組的定義裏access一詞的意思是“讀”,孤兒進程組成員試圖讀取控制終端時才拋EIO,對寫終端未做規定。

技術分享圖片

小結

這個故事說明,像W.Richard Stevens這種處在技術書籍第一列隊的作者,寫書不會含糊跳過的,因此一種省時間的看這位老哥的書的方式是,在書本裏找答案,不要自信跳過。

apue第九章 孤兒進程組例子