http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html
我看網上應該有不少搜索這個區別的問題,但是回答的都不全面,其中sigterm與sigint尤其有一點區別比較重要,但大都沒有提及,今天我就遇到了這個問題,糾結了20分鐘才搞明白咋回事。
首先,對於說這幾個信號都是終止程序運行的說法不太準確,因爲程序收到信號後,如果不對信號處理,就會導致程序退出,但如果程序捕獲信號進行處理,按照它的邏輯,它是不一定會退出的。
在這三個信號中,sigkill是不能被捕獲的,程序收到這個信號後,一定會退出。這就是kill -9一定能保證將程序殺死的原因。
下面說一下sigterm與sigint的區別,其中有一點區別區別很多文章都沒有提及,也是我寫這篇blog的原因(如果人家都寫了,我就不用寫了唄)
信號 |
產生方式 |
對進程的影響 |
sigint |
通過ctrl+c將會對當進程發送此信號 |
信號被當前進程樹接收到,也就是說,不僅當前進程會收到信號,它的子進程也會收到 |
sigterm |
kill命令不加參數就是發送這個信號 |
只有當前進程收到信號,子進程不會收到。如果當前進程被kill了,那麼它的子進程的父進程將會是init,也就是pid爲1的進程 |
下面這兩個代碼片段就能夠驗證這種情況(注意使用pcntl的時候,一定要declare ticks,要不然會杯具的發現函數沒有被調用,進程不退出,信號發過去沒有作用。php手冊竟然沒有強調這一點):
文件:loadhelper.php
04 |
$arr_processes = array (); |
06 |
function terminate( $signo ){ |
10 |
pcntl_signal(SIGTERM, "terminate" , true); |
11 |
pcntl_signal(SIGINT, "terminate" , true); |
13 |
foreach ( $argv as $key => $operation ){ |
20 |
$process = proc_open( $operation , array (),
& $pipes ); |
21 |
if (false === $process ){ |
24 |
$arr_processes [] = $process ; |
文件:child.php
03 |
pcntl_signal(SIGINT, "terminate" ); |
04 |
pcntl_signal(SIGTERM, "terminate" ); |
06 |
function terminate( $signo ){ |
使用命令php loadhelper.php “php test.php”可以啓動這個測試。
1.輸入ctrl+c發送sigint可以看到,父進程與子進程的terminate都得到了執行,都有輸出,但父進程不會退出,因爲子進程還沒有退出
2.通過kill向父進程的pid發送sigterm,可以看到,只有父進程輸出
遺留問題:
父進程(loadhelper)接受到一次信號後,如果在terminate函數中調用exit,它還是不能退出的,因爲還有子進程沒有退出。但是從此以後它就不能再接收信號了(子進程還是能夠接收到sigint),可能是exit使進程進入了待回收狀態,具體還 需要後續在分析一把。