當前位置:
首頁 > 最新 > 小說python中的孤兒進程

小說python中的孤兒進程

殭屍進程,大家都會對其嗤之以鼻,敬而遠之,畢竟臭名在外。

孤兒進程,大家對其都很寬容,甚至可以說是放縱,只因系統會收留。

然而,在實際應用中,孤兒進程雖然不會給系統造成直接性的危害,但更多時候會對業務造成一些影響,如當子進程為一個基於tcp的socket服務時,會造成主進程再次啟動時無法啟動,埠被佔用。主進程退出了,子進程會因為無法獲得某些資源,而變成業務上的"殭屍進程",這實際也是資源浪費。對於一些有進程監控的服務來說,可能會造成業務主服務無法重啟,或是進程不可控。

鑒於這些情況下,很多時候是不希望產生孤兒進程的,子進程應隨父進程結束而結束。

本文就小說一把如何做一個有擔當的"父親",不要不負責任的"一走了之",隨意丟棄自己的"孩子們"。

什麼是孤兒進程

孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程將成為孤兒進程。孤兒進程將被init進程(進程號為1)所收養,並由init進程對它們完成中止後的資源回收工作

通過下面的具體例子,具體看看

centralized_in_out服務會啟動8個子進程,父進程ID為5310,子進程ID為5312-5319

將父進程(5310)kill掉,可以看到子進程5312-5319全由ID為1的進程接管

如何做

上面看到子進程5312-5319被init進程接管了,但這不是我想要的結果,當前業務中,會再次拉起centralized_in_out服務,會再啟動8個子進程,這樣進程數太多,會失控,不符合業務需求。

我需要的是」父子共進退「,如何做呢?

豆瓣的工程師們,已經給出了解決辦法,具體參見:

https://github.com/douban/CaoE

修改代碼,用起來,效果如下

GIF

為什麼

豆瓣工程師給出了解決辦法,不能只拿來用用,得問幾個為什麼?通過什麼實現的?為什麼要這麼做呢?

下面具體分析下實現方法:

1. 方法概述

實現思路是通過創建一個子進程和孫子進程,子進程會監控父進程的狀態,當檢測到父進程退出後,會給進程組發送信號通知殺死孫子進程及其子進程。

這裡涉及到進程組信號兩個重要概念,下面具體闡述。

2. 概念闡述

進程組:每個進程都會屬於一個進程組(process group),每個進程組中可以包含多個進程。進程組會有一個領導進程 (process group leader),領導進程的PID成為進程組的ID (process group ID, PGID),用來標識進程組。

如下圖所示,centralized_in_out服務父進程的ID為5538(它的PGID為5538),子進程ID為5540(它的PGID為5540),孫子進程的ID為5541(它的PGID為5540),孫孫進程5542-5549的PGID都為5541

信號:具體概念這裡不多說了,有些大,而且晦澀難懂。主要涉及信號定義和處理函數的註冊綁定,後面結合代碼具體說明

3. 實現詳解

通過兩次fork,創建子進程(ID:5540)和孫進程(ID:5541),

其中子進程中有重要的一步,os.setpgrp()將子進程的進程組ID(5540)設為當前進程組的ID,後面孫進程和孫孫進程的進程組ID都為5540。

子進程在exit_when_parent_or_child_dies方法中循環等待父進程狀態,當PPID為1時,說明父進程已退出,通過killpg()將進程組中的所有進程(孫孫進程)殺死,然後自己退出。

到此,整個流程就清晰了,通過設置孫進程和孫孫進程的進程組ID為子進程的進程ID,當主進程退出,子進程被init進程接管時,通過killpg將同一個進程組ID的孫進程和孫孫進程中止。

但如果仔細看代碼,

exit_when_parent_or_child_dies方法中:

if os.getppid() == 1: 永遠執行不到,因為父進程退出時,捕獲如下信號

而這些信號處理方法中都會通過killpg殺死進程組,子進程也屬於這個進程組,也會被kill掉。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 chafezhou 的精彩文章:

TAG:chafezhou |