父進程退出時如何確保子進程退出?

来源:https://www.cnblogs.com/bianchengzhuji/archive/2019/02/15/10385827.html
-Advertisement-
Play Games

父進程退出時,子進程會如何?如何確保父進程退出時,子進程也退出? ...


原文地址:https://www.yanbinghu.com/2019/02/14/37859.html

前言

子進程退出的時候,父進程能夠收到子進程退出的信號,便於管理,但是有時候又需要在父進程退出的時候,子進程也退出,該怎麼辦呢?

父進程退出時,子進程會如何?

一般情況下,父進程退出後,是不會通知子進程的,這個時候子進程會成為孤兒進程,最終被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 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++,演算法,資料庫等編程相關[原創]技術文章,號內包含大量經典電子書和視頻學習資源。歡迎一起交流學習,一起修煉電腦“內功”,知其然,更知其所以然。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 信號處理 操作系統可以通過信號(signal)處理機制來實現一些功能:程式註冊好待監視的信號處理機制,在程式運行過程中如果產生了對應的信號,則會按照註冊好的處理方式進行處理。 signal基礎 每個進程都記錄了一個信號(signal)索引表,並註冊了各種信號的處理方式,每當收到信號的時候,會立即停止 ...
  • [TOC] 1.目標 爬取每個頁面鏈接的內部內容和投訴信息 2.方法1:通過Spider爬取 python coding: utf 8 import scrapy from dongguanSpider.items import DongguanItem class SunSpider(scrapy ...
  • 向後臺提交數據除了前端url,form表單,Ajax外還可以用cookie,secure_cookie,提交更多信息可以在用cookie基礎上用session, cookie,secure_cookie提交用戶數據:瀏覽器訪問1頁面,後端判斷前端瀏覽器提供的用戶對不對,對的話,設置cookie或se ...
  • 在ActiveMQ、RabbitMQ、RocketMQ、Kafka消息中間件之間,我們為什麼要選擇Kafka? ...
  • 前言 由於業務需要,需要在攔截器中操作Redis緩存,按照 controller,service層配置發現無法註入,一直報空指針異常。 解決方案 攔截器: 查詢原因 攔截器執行在Bean初始化之前導致這個問題的。在web.xml中各個元素的執行順序是這樣的,context param listene ...
  • 輸入:只能輸入A-Z(不區分大小寫),0-9和下劃線; 第一行輸入應輸入字元串,第二行輸入實際輸入字元串。 輸出:按大寫輸出缺少的字元,每個字元輸出一次。 註意: 1、由於不區分大小寫,則需要將小寫字母識別為大寫字母; 2、保證每個字元只出現一次。 思路: 1、將所有的字母都轉化為大寫字母; 2、挨 ...
  • 前言 前段時間,博客和論壇都放到的阿裡雲新購的三年 T5 實例伺服器上,等都轉移過去才發現,所謂的 T5 實例只能滿足10% 的 CPU 峰值。期間經歷了各種卡頓、死機,最終又把博客單獨遷移了回來。靜態文件走 CDN,文章都 Redis,以為萬事大吉了就。 群壓 然並卵,有一天,群里有網友說要壓測我 ...
  • 啟動了兩個goroutine,並完成一些工作。在各自迴圈的每次迭代之後,在goroutine 會使用LoadInt64 來檢查shutdown 變數的值。這個函數會安全地返回shutdown 變數的一個副本。如果這個副本的值為1,goroutine 就會跳出迴圈並終止。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...