APUE 第三版 程序 9-12 (創建孤兒進程組)

 
孤兒進程組的定義:該進程組的每個成員的父進程要麼是該組的成員,要麼在其它會話中。
 
孤兒進程組的特點

  1. 如果一個進程組包含一個或一個以上的停止的進程,當該進程組變成孤兒進程組時,該進程組中的每一個進程都會接收到一個 SIGHUP (掛掉)信號,然後緊接着會接收到 SIGCONT (繼續)信號。
    但是對掛斷信號的系統默認動作是終止該進程。所以,如果要繼續執行子進程,就必須提供一個信號處理程序以捕捉該信號。

  2. 孤兒進程組是後臺進程組

  3. 孤兒進程組去讀控制終端時,read返回出錯並將errno設置爲EIO。
    只有前臺作業能接收終端輸入,如果後臺作業試圖讀終端,那麼這並不是一個錯誤,但是終端驅動程序將檢測到這種情況,並且向後臺作業發送一個特定的信號SIGTTIN。該信號通常會暫時停止此後臺作業。由於孤兒進程組是後臺進程組,如果內核用SIGTTIN信號停止它,那麼進程組中的進程就再也不會繼續了。

 
  至於書中說:父進程在終止時,子進程變成了後臺進程組,因爲父進程是由 shell 作爲前臺作業執行的。不懂什麼意思,有沒有老哥解釋一下,爲什麼會變成後臺進程組。
 
 
  程序 9-12代碼:

#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)
		sleep(5);
	else {
		pr_ids("child");
		signal(SIGHUP, sig_hup);
		kill(getpid(), SIGTSTP);
		pr_ids("child");
		if(read(STDIN_FILENO, &c, 1) != 1)
			printf("read error %d on controlling TTY\n", errno);
	}
	exit(0);
}

終端運行如下:

hjm@hjm-Inspiron:~$ ./9-12
parent: pid = 2792, ppid = 2758, pgrp = 2792, tpgrp = 2792
child: pid = 2793, ppid = 2792, pgrp = 2792, tpgrp = 2792
SIGHUP received, pid = 2793
child: pid = 2793, ppid = 1, pgrp = 2792, tpgrp = 2758
read error 5 on controlling TTY

【析】:
由輸出可知,起初 child 屬於一個前臺進程組。當其父進程結束時,該子進程的進程組成爲了孤兒進程組,後臺進程組。

   它試圖對讀標準輸入,正常情況下,將對該後臺進程組產生 SIGTTIN 信號,該信號會停止此後臺作業。!但是這是一個孤兒進程組,如果內核用SIGTTIN信號停止它,那麼進程組中的進程就再也不會繼續了。所以 POSIX.1 對這種情況下的處理是,read 返回出錯,並將 errno 設置爲 5.
   

   至於孤兒進程組的輸出,這個取決於是否禁止後臺作業輸出到控制終端。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章