php 孤儿进程组,孤儿进程组(Orphaned Process Groups) APUE2学习笔记

1)先说明孤儿进程(orphan process)的概念:

一个其父进程已终止的进程称为孤儿进程(orphan process),这种进程由 init 进程”收养“。

本文中,讨论的是孤儿进程组:

2)孤儿进程组(orphaned process group):

POSIX.1 将孤儿进程组定义为:该组中每个成员的父进程要么是该组中的一个成员,要么不是该组所属会话(session)的成员。

对孤儿进程组的另一种描述:一个进程组不是孤儿进程组的条件是,该组中有一个进程,其父进程在属于同一个会话(session)的另一个组中。

2.对孤儿进程的说明

父进程终止后,进程组成为孤儿进程组,POSIX.1 要求内核向新的孤儿进程组中处于停止状态的每一个进程发送挂断信号(SIGHUP),接着又向其发送继续运行信号(SIGCONT)。

unix(linux) 对挂断信号(SIGHUP)的系统默认动作是终止该进程,为此,必须提供一个信号处理程序以捕捉该信号。

3. 下面以一个父进程 + 一个子进程 组成的进程组为例,理解进程组成为孤儿进程组(本例中:该孤儿进程组就这一个子进程)后的行为。 下图是本例中的进程关系。

30467117_1.gif

示例代码:(对原文代码做了适当修改)

#include stdio.h>

#include stdlib.h>

#include unistd.h>

#include signal.h>

#include errno.h>

#define errexit(msg) do{ perror(msg); exit(EXIT_FAILURE); } while(0)

static void sig_hup(int signo)

{

printf("SIGHUP received, pid = %d\n", getpid());

}

static void sig_cont(int signo)

{

printf("SIGCONT received, pid = %d\n", getpid());

}

static void sig_ttin(int signo)

{

printf("SIGTTIN received, pid = %d\n", getpid());

}

static void pr_ids(char *name)

{

printf("%s: pid = %d, ppid = %d, pgrp = %d, tpgrp = %d\n",

name, getpid(), getppid(), getpgrp(), tcgetpgrp(STDIN_FILENO));

}

int main(int argc, char *argv[])

{

char c;

pid_t pid;

setbuf(stdout, NULL);

pr_ids("parent");

if ((pid = fork())  0) {

errexit("fork error");

} else if (pid > 0) { /* parent */

sleep(5);

printf("parent exit\n");

exit(0);

} else { /* child */

pr_ids("child...1");

signal(SIGCONT, sig_cont);

signal(SIGHUP, sig_hup);

signal(SIGTTIN, sig_ttin);

kill(getpid(), SIGTSTP);

//sleep(10);

pr_ids("child...2");

if (read(STDIN_FILENO, &c, 1) != 1) {

printf("read error from controlling TTY, errno = %d\n", errno);

}

printf("child exit\n");

}

exit(0);

}

将改程序编译成: m

程序执行结果:

1) 程序中使用 kill(getpid(), SIGTSTP); 使进程停止

[liumin@localhost orphan]$ ./m

parent: pid = 15028, ppid = 8611, pgrp = 15028, tpgrp = 15028

child...1: pid = 15029, ppid = 15028, pgrp = 15028, tpgrp = 15028

parent exit

SIGCONT received, pid = 15029

[liumin@localhost orphan]$ SIGHUP received, pid = 15029

child...2: pid = 15029, ppid = 1, pgrp = 15028, tpgrp = 8611

read error from controlling TTY, errno = 5

child exit

[liumin@localhost orphan]$

=================================================

2.将sleep 函数前的注释去掉,注释 kill 函数调用,就不会发送信号了(因为这个时候,进程不是处于停止状态,只有在停止状态时,孤儿进程组才会接收到 SIGHUP + SIGCONT 信号):

[liumin@localhost orphan]$ ./m

parent: pid = 15216, ppid = 8611, pgrp = 15216, tpgrp = 15216

child...1: pid = 15217, ppid = 15216, pgrp = 15216, tpgrp = 15216

parent exit

[liumin@localhost orphan]$ child...2: pid = 15217, ppid = 1, pgrp = 15216, tpgrp = 8611

read error from controlling TTY, errno = 5

child exit

[liumin@localhost orphan]$

在进程中调用 pr_ids后,程序试图读标准输入。一般情况下,当后台进程组试图读控制终端时,则对该后台进程组产生 SIGTTIN

信号,其默认动作是停止进程。但是在这里,这是一个孤儿进程组,如果内核用此信号停止它,则此进程组中的进程就再也不会继续。 POSIX.1

规定,在这种情况下, read 函数返回出错,并将其errno 设置为 EIO。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值