国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP多進(jìn)程初探 --- 信號(hào)

Prasanta / 706人閱讀

摘要:第一次子進(jìn)程正在休眠中,父進(jìn)程依舊在循環(huán)中。第三次此時(shí)父進(jìn)程已經(jīng)執(zhí)行了,將已經(jīng)退出的子進(jìn)程回收,釋放了等資源。梳理一下流程,子進(jìn)程向父進(jìn)程發(fā)送信號(hào)是對(duì)人們來(lái)說(shuō)是透明的,也就是說(shuō)我們無(wú)須關(guān)心。

[原文地址:https://blog.ti-node.com/blog...]

上一篇尬聊了通篇的pcntl_wait()和pcntl_waitpid(),就是為了解決僵尸進(jìn)程的問(wèn)題,但最后看起來(lái)還是有一些遺留問(wèn)題,而且因?yàn)樽烨吩谏掀恼碌慕Y(jié)尾出也給了解決方案:信號(hào)。

信號(hào)是一種軟件中斷,也是一種非常典型的異步事件處理方式。在NIX系統(tǒng)誕生的混沌之初,信號(hào)的定義是比較混亂的,而且最關(guān)鍵是不可靠,這是一個(gè)很嚴(yán)重的問(wèn)題。所以在后來(lái)的POSIX標(biāo)準(zhǔn)中,對(duì)信號(hào)做了標(biāo)準(zhǔn)化同時(shí)也各個(gè)發(fā)行版的NIX也都提供大量可靠的信號(hào)。每種信號(hào)都有自己的名字,大概如SIGTERM、SIGHUP、SIGCHLD等等,在*NIX中,這些信號(hào)本質(zhì)上都是整形數(shù)字(游有心情的可以參觀一下signal.h系列頭文件)。

信號(hào)的產(chǎn)生是有多種方式的,下面是常見(jiàn)的幾種:

鍵盤上按某些組合鍵,比如Ctrl+C或者Ctrl+D等,會(huì)產(chǎn)生SIGINT信號(hào)。

使用posix kill調(diào)用,可以向某個(gè)進(jìn)程發(fā)送指定的信號(hào)。

遠(yuǎn)程ssh終端情況下,如果你在服務(wù)器上執(zhí)行了一個(gè)阻塞的腳本,正在阻塞過(guò)程中你關(guān)閉了終端,可能就會(huì)產(chǎn)生SIGHUP信號(hào)。

硬件也會(huì)產(chǎn)生信號(hào),比如OOM了或者遇到除0這種情況,硬件也會(huì)向進(jìn)程發(fā)送特定信號(hào)。

而進(jìn)程在收到信號(hào)后,可以有如下三種響應(yīng):

直接忽略,不做任何反映。就是俗稱的完全不鳥(niǎo)。但是有兩種信號(hào),永遠(yuǎn)不會(huì)被忽略,一個(gè)是SIGSTOP,另一個(gè)是SIGKILL,因?yàn)檫@兩個(gè)進(jìn)程提供了向內(nèi)核最后的可靠的結(jié)束進(jìn)程的辦法。

捕捉信號(hào)并作出相應(yīng)的一些反應(yīng),具體響應(yīng)什么可以由用戶自己通過(guò)程序自定義。

系統(tǒng)默認(rèn)響應(yīng)。大多數(shù)進(jìn)程在遇到信號(hào)后,如果用戶也沒(méi)有自定義響應(yīng),那么就會(huì)采取系統(tǒng)默認(rèn)響應(yīng),大多數(shù)的系統(tǒng)默認(rèn)響應(yīng)就是終止進(jìn)程。

用人話來(lái)表達(dá),就是說(shuō)假如你是一個(gè)進(jìn)程,你正在干活,突然施工隊(duì)的喇叭里沖你嚷了一句:“吃飯了!”,于是你就放下手里的活兒去吃飯。你正在干活,突然施工隊(duì)的喇叭里沖你嚷了一句:“發(fā)工資了!”,于是你就放下手里的活兒去領(lǐng)工資。你正在干活,突然施工隊(duì)的喇叭里沖你嚷了一句:“有人找你!”,于是你就放下手里的活兒去看看是誰(shuí)找你什么事情。當(dāng)然了,你很任性,那是完全可以不鳥(niǎo)喇叭里喊什么內(nèi)容,也就是忽略信號(hào)。也可以更任性,當(dāng)喇叭里沖你嚷“吃飯”的時(shí)候,你去就不去吃飯,你去睡覺(jué),這些都可以由你來(lái)。而你在干活過(guò)程中,從來(lái)不會(huì)因?yàn)橐饶硞€(gè)信號(hào)就不干活了一直等信號(hào),而是信號(hào)隨時(shí)隨地都可能會(huì)來(lái),而你只需要在這個(gè)時(shí)候作出相應(yīng)的回應(yīng)即可,所以說(shuō),信號(hào)是一種軟件中斷,也是一種異步的處理事件的方式。

回到上文所說(shuō)的問(wèn)題,就是子進(jìn)程在結(jié)束前,父進(jìn)程就已經(jīng)先調(diào)用了pcntl_waitpid(),導(dǎo)致子進(jìn)程在結(jié)束后依然變成了僵尸進(jìn)程。實(shí)際上在父進(jìn)程不斷while循環(huán)調(diào)用pcntl_waitpid()是個(gè)解決辦法,大概代碼如下:

$pid = pcntl_fork();
if( 0 > $pid ){
  exit("fork error.".PHP_EOL);
} else if( 0 < $pid ) {
  // 在父進(jìn)程中
  cli_set_process_title("php father process");
  // 父進(jìn)程不斷while循環(huán),去反復(fù)執(zhí)行pcntl_waitpid(),從而試圖解決已經(jīng)退出的子進(jìn)程
  while( true ){
    sleep( 1 );
    pcntl_waitpid( $pid, &$status, WNOHANG );
  }
} else if( 0 == $pid ) {
  // 在子進(jìn)程中
  // 子進(jìn)程休眠3秒鐘后直接退出
  cli_set_process_title("php child process");
  sleep( 20 );
  exit;
}

下圖是運(yùn)行結(jié)果:

解析一下這個(gè)結(jié)果,我先后三次執(zhí)行了ps -aux | grep php去查看這兩個(gè)php進(jìn)程。

第一次:子進(jìn)程正在休眠中,父進(jìn)程依舊在循環(huán)中。

第二次:子進(jìn)程已經(jīng)退出了,父進(jìn)程依舊在循環(huán)中,但是代碼還沒(méi)有執(zhí)行到pcntl_waitpid(),所以在子進(jìn)程退出后到父進(jìn)程執(zhí)行回收前這段空隙內(nèi)子進(jìn)程變成了僵尸進(jìn)程。

第三次:此時(shí)父進(jìn)程已經(jīng)執(zhí)行了pcntl_waitpid(),將已經(jīng)退出的子進(jìn)程回收,釋放了pid等資源。

但是這樣的代碼有一個(gè)缺陷,實(shí)際上就是子進(jìn)程已經(jīng)退出的情況下,主進(jìn)程還在不斷while pcntl_waitpid()去回收子進(jìn)程,這是一件很奇怪的事情,并不符合社會(huì)主義主流價(jià)值觀,不低碳不節(jié)能,代碼也不優(yōu)雅,不好看。所以,應(yīng)該考慮用更好的方式來(lái)實(shí)現(xiàn)。那么,我們篇頭提了許久的信號(hào)終于概要出場(chǎng)了。

現(xiàn)在讓我們考慮一下,為何信號(hào)可以解決“不低碳不節(jié)能,代碼也不優(yōu)雅,不好看”的問(wèn)題。子進(jìn)程在退出的時(shí)候,會(huì)向父進(jìn)程發(fā)送一個(gè)信號(hào),叫做SIGCHLD,那么父進(jìn)程一旦收到了這個(gè)信號(hào),就可以作出相應(yīng)的回收動(dòng)作,也就是執(zhí)行pcntl_waitpid(),從而解決掉僵尸進(jìn)程,而且還顯得我們代碼優(yōu)雅好看節(jié)能環(huán)保。

梳理一下流程,子進(jìn)程向父進(jìn)程發(fā)送SIGCHLD信號(hào)是對(duì)人們來(lái)說(shuō)是透明的,也就是說(shuō)我們無(wú)須關(guān)心。但是,我們需要給父進(jìn)程安裝一個(gè)響應(yīng)SIGCHLD信號(hào)的處理器,除此之外,還需要讓這些信號(hào)處理器運(yùn)行起來(lái),安裝上了不運(yùn)行是一件尷尬的事情。那么,在php里給進(jìn)程安裝信號(hào)處理器使用的函數(shù)是pcntl_signal(),讓信號(hào)處理器跑起來(lái)的函數(shù)是pcntl_signal_dispatch()。

pcntl_signal(),安裝一個(gè)信號(hào)處理器,具體說(shuō)明是pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] ),參數(shù)signo就是信號(hào),callback則是響應(yīng)該信號(hào)的代碼段,返回bool值。

pcntl_signal_dispatch(),調(diào)用每個(gè)等待信號(hào)通過(guò)pcntl_signal() 安裝的處理器,參數(shù)為void,返回bool值。

下面結(jié)合新引入的兩個(gè)函數(shù)來(lái)解決一下樓上的丑陋代碼:

$pid = pcntl_fork();
if( 0 > $pid ){
  exit("fork error.".PHP_EOL);
} else if( 0 < $pid ) {
  // 在父進(jìn)程中
  // 給父進(jìn)程安裝一個(gè)SIGCHLD信號(hào)處理器
  pcntl_signal( SIGCHLD, function() use( $pid ) {
    echo "收到子進(jìn)程退出".PHP_EOL;
    pcntl_waitpid( $pid, $status, WNOHANG );
  } );
  cli_set_process_title("php father process");
  // 父進(jìn)程不斷while循環(huán),去反復(fù)執(zhí)行pcntl_waitpid(),從而試圖解決已經(jīng)退出的子進(jìn)程
  while( true ){
    sleep( 1 );
    // 注釋掉原來(lái)老掉牙的代碼,轉(zhuǎn)而使用pcntl_signal_dispatch()
    //pcntl_waitpid( $pid, &$status, WNOHANG );
    pcntl_signal_dispatch();
  }
} else if( 0 == $pid ) {
  // 在子進(jìn)程中
  // 子進(jìn)程休眠3秒鐘后直接退出
  cli_set_process_title("php child process");
  sleep( 20 );
  exit;
}

運(yùn)行結(jié)果如下:


[原文地址:https://blog.ti-node.com/blog...]

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/29328.html

相關(guān)文章

  • PHP進(jìn)程初探 --- 利用進(jìn)程開(kāi)發(fā)點(diǎn)兒東西吧

    摘要:主進(jìn)程退出子進(jìn)程繼續(xù)執(zhí)行給進(jìn)程重新起個(gè)名字加入我們出個(gè)子進(jìn)程就可以搞定這些任務(wù),那么出個(gè)子進(jìn)程,同時(shí)父進(jìn)程要負(fù)責(zé)這個(gè)子進(jìn)程的狀態(tài)等。 [原文地址:https://blog.ti-node.com/blog...] 干巴巴地叨逼叨了這么久,時(shí)候表演真正的技術(shù)了! 做個(gè)高端點(diǎn)兒的玩意吧,加入我們要做一個(gè)任務(wù)系統(tǒng),這個(gè)系統(tǒng)可以在后臺(tái)幫我們完成一大波(注意是一大波)數(shù)據(jù)的處理,那么我們自然想到...

    huaixiaoz 評(píng)論0 收藏0
  • PHP進(jìn)程初探 --- 進(jìn)程間通信二三事

    摘要:多進(jìn)程通信之一命名管道。多進(jìn)程通信之三信號(hào)量與共享內(nèi)存。共享內(nèi)存是最快是進(jìn)程間通信方式,因?yàn)閭€(gè)進(jìn)程之間并不需要數(shù)據(jù)復(fù)制,而是直接操控同一份數(shù)據(jù)。的一些書(shū)籍中甚至不建議新手輕易使用這種進(jìn)程間通信的方式,因?yàn)檫@是一種極易產(chǎn)生死鎖的解決方案。 [原文地址:https://blog.ti-node.com/blog...] 往往開(kāi)啟多進(jìn)程的目的是為了一起干活加速效率,前面說(shuō)了不同進(jìn)程之間的內(nèi)存...

    hearaway 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<