天天看點

【APUE】6、孤兒程序組

關于孤兒程序組,我認為就是目前會話中的所有程序的父程序都不在目前會話中,那麼這個會話中的程序就是孤兒程序組

/**
 * 功能:我們建立一個孤兒程序or程序組
 * 時間:2015年12月19日17:01:48
 * 作者:cutter_point
 */
#include "../util/apue.h"
#include "../util/error.c"

#include <errno.h>

//用來處理挂斷信号的函數
static void sig_hup(int signo)
{
	printf("收到挂斷信号,pid=%ld\n", (long)getpid());
}

//輸出相應的id号
static void pr_ids(char *name)
{
	printf("%s: 目前程序id = %ld, 父程序id = %ld, 目前程序組 = %ld, 前台程序組 = %ld\n",
	    name, (long)getpid(), (long)getppid(), (long)getpgrp(),
	    (long)tcgetpgrp(STDIN_FILENO));
	//清空緩存
	fflush(stdout);
}

int main(int argc, char *argv[])
{
	char c;
	pid_t pid;	//存放程序id

	//輸出父程序的一些id值
	pr_ids("父程序");
	if((pid = fork()) < 0)
		err_sys("fork失敗");
	else if(pid > 0)
		sleep(5);	//為了子程序在父程序結束之前還可以執行一段
	else
	{
		pr_ids("子程序");
		//建立信号機制,signal第二個參數 typedef void (*sighandler_t)(int);這個是一個int參數的函數指針
		signal(SIGHUP, sig_hup);	//這個是挂斷信号
		/*
		SIGSTOP:停止(stopped)程序的執行. 
			注意它和terminate以及interrupt的差別:該程序還未結束, 隻是暫停執行. 
			本信号不能被阻塞, 處理或忽略.

		SIGTSTP:停止程序的運作, 但該信号可以被處理和忽略. 使用者鍵入SUSP字元時(通常是Ctrl-Z)發出這個信号
		*/
		kill(getpid(), SIGTSTP);	//用于向任何程序組或程序發送信号。
		pr_ids("子程序");
		if(read(STDIN_FILENO, &c, 1) != 1)
			printf("讀取錯誤代碼: %d on controlling TTY\n", errno);
	}//else

	exit(0);
}
           

執行的結果:

【APUE】6、孤兒程式組

首先我們得到父程序的一系列id号,然後我們把父程序sleep,執行子程序檢視子程序的一系列id号,我們發現沒什麼問題,那麼目前的程序都是ok的

好的,接下來我們建立信号機制,當我們父程序挂斷的時候,用來提示

然後調用kill函數暫停我們的子程序,注意暫停,不是關閉,然後父程序結束之後子程序的父程序結束,那麼子程序交給init托管,是以父程序id變為1,前台組也變成了父程序的父程序id組,是以這個時候子程序所在的組變成了一個孤兒程序組!!!

我們還可以吧父程序的sleep修改為sleep(0),執行之後我們會發現,後面子程序都變成第二個結果了,因為子程序還沒執行,父程序就已經結束了,子程序早早成為孤兒程序

/**
 * 功能:我們建立一個孤兒程序or程序組,修改
 * 時間:2015年12月19日17:26:46
 * 作者:cutter_point
 */
#include "../util/apue.h"
#include "../util/error.c"

#include <errno.h>

//用來處理挂斷信号的函數
static void sig_hup(int signo)
{
	printf("收到挂斷信号,pid=%ld\n", (long)getpid());
}

//輸出相應的id号
static void pr_ids(char *name)
{
	printf("%s: 目前程序id = %ld, 父程序id = %ld, 目前程序組 = %ld, 前台程序組 = %ld\n",
	    name, (long)getpid(), (long)getppid(), (long)getpgrp(),
	    (long)tcgetpgrp(STDIN_FILENO));	//一般是0,1,2
	//清空緩存
	//fflush(stdout);
}

int main(int argc, char *argv[])
{
	char c;
	pid_t pid;	//存放程序id

	//輸出父程序的一些id值
	pr_ids("父程序");
	if((pid = fork()) < 0)
		err_sys("fork失敗");
	else if(pid > 0)
		sleep(0);	//為了子程序在父程序結束之前還可以執行一段
	else
	{
		pr_ids("子程序");
		//建立信号機制,signal第二個參數 typedef void (*sighandler_t)(int);這個是一個int參數的函數指針
		signal(SIGHUP, sig_hup);	//這個是挂斷信号,這個要在kill之前,不然程序停止在哪裡就無法使用了
		/*
		SIGSTOP:停止(stopped)程序的執行. 
			注意它和terminate以及interrupt的差別:該程序還未結束, 隻是暫停執行. 
			本信号不能被阻塞, 處理或忽略.

		SIGTSTP:停止程序的運作, 但該信号可以被處理和忽略. 使用者鍵入SUSP字元時(通常是Ctrl-Z)發出這個信号
		*/
		printf("#############################begin\n");
		kill(getpid(), SIGTSTP);	//用于向任何程序組或程序發送信号。
		printf("#############################end\n");
		pr_ids("子程序");
		
		if(read(STDIN_FILENO, &c, 1) != 1)
			printf("讀取錯誤代碼: %d on controlling TTY\n", errno);
	}//else

	exit(0);
}
           

這是看不到子程序變為孤兒程序的過程的!!!