父进程退出时如何确保子进程退出

前言

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

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

一般情况下,父进程退出后,是不会通知子进程的,这个时候子进程会成为孤儿进程,最终被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.\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 <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.\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进程。

交流

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

微信公众号【编程珠玑】:专注但不限于分享计算机编程基础,Linux,C语言,C++,算法,数据库等编程相关[原创]技术文章,号内包含大量经典电子书和视频学习资源。欢迎一起交流学习,一起修炼计算机“内功”,知其然,更知其所以然。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容