找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3532|回复: 13

C++干货问题,父进程退出时如何确保子进程退出?

[复制链接]
  • 打卡等级:常驻代表
  • 打卡总天数:34
  • 打卡月天数:6
  • 打卡总奖励:9027
  • 最近打卡:2025-12-17 23:15:51

2823

主题

541

回帖

2万

积分

管理员

积分
22569
发表于 2019-3-8 19:11:35 | 显示全部楼层 |阅读模式
前言
子进程退出的时候,父进程能够收到子进程退出的信号,便于管理,但是有时候又需要在父进程退出的时候,子进程也退出,该怎么办呢?
父进程退出时,子进程会如何?
一般情况下,父进程退出后,是不会通知子进程的,这个时候子进程会成为孤儿进程,最终被init进程收养。我们先来看一下这种情况。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

int main(void)
{
    pid_t pid;
    //fork一个进程
    pid = fork();
    //创建失败
    if (pid < 0)
    {
        perror("fork error:");
        exit(1);
    }
    //子进程
    if (pid == 0)
    {
        printf("child process.
");
        printf("child  pid:%d,parent pid:%d
",getpid(),getppid());
        printf("sleep 10 seconds.
");
        //sleep一段时间,让父进程先退出,为了便于观察,sleep 10s
        sleep(10);

        printf("now child pid: %d parent pid:%d
",getpid(),getppid());
    }
    //父进程
    else
    {
        printf("parent process.
");
        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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <signal.h>
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.
");
        printf("child  pid:%d,parent pid:%d
",getpid(),getppid());
        printf("sleep 10 seconds.
");
        //sleep一段时间,让父进程先退出,为了便于观察,sleep 10s
        sleep(10);

        printf("now child pid: %d parent pid:%d
",getpid(),getppid());
    }
    //父进程
    else
    {
        printf("parent process.
");
        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进程。
交流
虽然本文方法可行,但并不适用于所有操作系统,你有什么更好的办法解决上面的问题?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
工控课堂 www.gkket.com

0

主题

169

回帖

503

积分

中级会员

积分
503
发表于 2019-3-8 19:52:00 | 显示全部楼层
看完楼主的帖子,我的心情竟是久久不能平息,受教了
工控课堂 www.gkket.com

0

主题

172

回帖

537

积分

中级会员

积分
537
发表于 2019-3-8 20:00:07 | 显示全部楼层
谢谢您的分享!
工控课堂 www.gkket.com

0

主题

169

回帖

376

积分

注册会员

积分
376
发表于 2019-3-8 20:19:14 | 显示全部楼层
我只是路过打酱油的。
工控课堂 www.gkket.com

0

主题

148

回帖

373

积分

注册会员

积分
373
发表于 2019-3-8 20:19:24 | 显示全部楼层
谢谢您的分享!
工控课堂 www.gkket.com

0

主题

137

回帖

350

积分

注册会员

积分
350
发表于 2019-3-8 20:21:19 | 显示全部楼层
老师四个微信公众号都可以关注吗?是否有免费资料下载!
工控课堂 www.gkket.com

0

主题

215

回帖

847

积分

中级会员

积分
847
发表于 2019-5-16 11:58:06 | 显示全部楼层
绝对干货,楼主给力,支持了!!!
工控课堂 www.gkket.com

0

主题

439

回帖

2772

积分

高级会员

积分
2772
发表于 2019-6-12 09:34:50 | 显示全部楼层
我只是路过打酱油的。
工控课堂 www.gkket.com

0

主题

97

回帖

361

积分

注册会员

积分
361
发表于 2019-6-15 17:48:03 | 显示全部楼层
无私奉献,好工控人,32个赞送给你!!
工控课堂 www.gkket.com

0

主题

231

回帖

2670

积分

高级会员

积分
2670
发表于 2025-12-2 00:50:14 | 显示全部楼层
原来还有这种操作,长见识了!
工控课堂 www.gkket.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|手机版|免责声明|本站介绍|工控课堂 ( 沪ICP备20008691号-1 )

GMT+8, 2025-12-22 16:56 , Processed in 0.142423 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表