java子进程退出_父进程退出时如何确保子进程退出?

前言

子进程退出的时候,父进程能够收到子进程退出的信号,便于管理,但是有时候又需要在父进程退出的时候,子进程也退出,该怎么办呢?

父进程退出时,子进程会如何?

一般情况下,父进程退出后,是不会通知子进程的,这个时候子进程会成为孤儿进程,最终被init进程收养。我们先来看一下这种情况。

#include

#include

#include

#include

int main(void)

{

pid_t pid;

//fork一个进程

pid = fork();

//创建失败

if (pid < 0)

{

perror("fork error:");

exit(1);

}

//子进程

if (pid == 0)

{

printf("child process.\n");

printf("child pid:%d,parent pid:%d\n",getpid(),getppid());

printf("sleep 10 seconds.\n");

//sleep一段时间,让父进程先退出,为了便于观察,sleep 10s

sleep(10);

printf("now child pid: %d parent pid:%d\n",getpid(),getppid());

}

//父进程

else

{

printf("parent process.\n");

sleep(1);

}

return 0;

}

在这个程序中,我们为了让父进程先退出,子进程sleep了10秒。

运行结果如下:

parent process.

child process.

child pid:17433,parent pid:17432

sleep 10 seconds.

now child pid: 17433 parent pid:1658

从结果中可以看到,一开始子进程17433的父进程id是17432,但是在10秒后,它的父进程变成了1658。1685是什么进程呢?

$ ls -al /proc/1658/exe

/proc/1658/exe -> /sbin/upstart

由于我使用的环境是带有图形界面的ubuntu系统,所以最终并不是被我们所熟知的init进程收养,而是被一个名为/sbin/upstart的进程所收养。另外还可以观察到,该进程也是其他系统进程的父进程。

如何确保父进程退出的同时,子进程也退出?

既然如此,如何确保父进程退出的同时,子进程也退出呢?或许我们可以在子进程和父进程之间建立通信管道,一旦通信异常,则认为父进程退出,子进程自己也回收资源退出。但是这样做总觉得不是很正经。有没有已有的函数帮我们做这件事呢?prctl函数可以帮助我们。第一个参数中,有一个选项,叫做PR_GET_PDEATHSIG:

PR_SET_PDEATHSIG (since Linux 2.1.57)

Set the parent death signal of the calling process to arg2 (either a signal value in the range 1..maxsig, or 0 to clear).

This is the signal that the calling process will get when its parent dies. This value is cleared for the child of a fork(2)

and (since Linux 2.4.36 / 2.6.23) when executing a set-user-ID or set-group-ID binary, or a binary that has associated capa‐

bilities (see capabilities(7)). This value is preserved across execve(2).

内容很多,主要意思为:设置一个信号,当父进程退出的时候,子进程将会收到该信号。

那么根据这个,我们完全可以在父进程退出时,也给子进程一个退出的信号。程序代码如下:

#include

#include

#include

#include

#include

#include

int main(void)

{

pid_t pid;

//fork一个进程

pid = fork();

//创建失败

if (pid < 0)

{

perror("fork error:");

exit(1);

}

//子进程

if (pid == 0)

{

/*父进程退出时,会收到SIGKILL信号*/

prctl(PR_SET_PDEATHSIG,SIGKILL);

printf("child process.\n");

printf("child pid:%d,parent pid:%d\n",getpid(),getppid());

printf("sleep 10 seconds.\n");

//sleep一段时间,让父进程先退出,为了便于观察,sleep 10s

sleep(10);

printf("now child pid: %d parent pid:%d\n",getpid(),getppid());

}

//父进程

else

{

printf("parent process.\n");

sleep(1);

}

return 0;

}

运行结果:

parent process.

child process.

child pid:17625,parent pid:17624

sleep 10 seconds.

可以看到,由于加入了

prctl(PR_SET_PDEATHSIG,SIGKILL);

在父进程退出时,子进程将会收到SIGKILL信号,而进程收到该信号的默认动作则是退出。因而最后不会看到它成为孤儿进程,被其他进程所收养。需要注意的是,该函数并非所有系统都支持。

总结

有些情况下,我们常常需要父子进程共存亡,子进程退出时,父进程可以通过wait捕捉子进程的退出状态,但是父进程退出时,子进程却难以得知。因此,在最初fork子进程的时候,便表明了,当父进程退出的时候,子进程收到SIGKILL信号,最终也退出。以此达到同生共死的目的。当然也可以发送其他信号,由子进程捕获该信号并做后续处理。

练习

尝试将上面的代码在非图形界面的linux操作系统中运行,看看最终被收养的是否为init进程。

交流

虽然本文方法可行,但并不适用于所有操作系统,你有什么更好的办法解决上面的问题?

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值