IT培訓(xùn)-高端面授IT培訓(xùn)機(jī)構(gòu)
          云和教育:云和數(shù)據(jù)集團(tuán)高端IT職業(yè)教育品牌
          • 國(guó)家級(jí)
            全民數(shù)字素養(yǎng)與技能培訓(xùn)基地
          • 河南省
            第一批產(chǎn)教融合型企業(yè)建設(shè)培育單位
          • 鄭州市
            數(shù)字技能人才(碼農(nóng))培養(yǎng)評(píng)價(jià)聯(lián)盟

          PHP如何優(yōu)雅的處理信號(hào)?看完這篇文章你就知道了!

          • 發(fā)布時(shí)間:
            2019-08-01
          • 版權(quán)所有:
            云和教育
          • 分享:

          PHP進(jìn)程間通信的另外一個(gè)手段就是通過信號(hào)來在進(jìn)程間傳遞信息。信號(hào)是一種系統(tǒng)調(diào)用,通常我們用的kill命令就是發(fā)送某個(gè)信號(hào)給某個(gè)進(jìn)程的。

          在開發(fā)服務(wù)器端守護(hù)進(jìn)程方面,信號(hào)處理至關(guān)重要。PHP的pcntl擴(kuò)展提供了信號(hào)處理的功能,利用它可以讓PHP來接管信號(hào)的處理。

          配圖1 PHP如何優(yōu)雅的處理信號(hào).jpg

          今天,我們就來給大家講一講PHP中的信號(hào)處理。

          什么是信號(hào)?

          信號(hào)是事件發(fā)生時(shí)對(duì)進(jìn)程的通知機(jī)制,有時(shí)又稱為軟件中斷。一個(gè)進(jìn)程可以向另一個(gè)進(jìn)程發(fā)送信號(hào),比如子進(jìn)程結(jié)束時(shí)都會(huì)向父進(jìn)程發(fā)送一個(gè)SIGCHLD(17號(hào)信號(hào))來通知父進(jìn)程,所以有時(shí)信號(hào)也被當(dāng)作一種進(jìn)程間通信的機(jī)制。

          信號(hào)的產(chǎ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ā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):

          ●直接忽略,不做任何反映。就是俗稱的完全不鳥。但是有兩種信號(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)什么可以由用戶自己通過程序自定義。

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

          PHP信號(hào)處理案例

          我們?cè)贔PM模式下寫代碼,不會(huì)遇到信號(hào)處理相關(guān)的問題,但是CLI模式下一些常駐內(nèi)存的腳本,如何能夠自由的重啟、關(guān)閉、退出前做一些清理工作(斷開鏈接,刪除臨時(shí)文件等)?

          配圖2 PHP如何優(yōu)雅的處理信號(hào).jpg

          pcntl_signal是PHP的信號(hào)處理注冊(cè)方法,這個(gè)是pcntl初始化的時(shí)候,將pcntl_signal_dispatch注冊(cè)為tick的處理函數(shù)。

          配圖3 PHP如何優(yōu)雅的處理信號(hào).jpg

          pcntl_signal會(huì)將處理函數(shù)放到信號(hào)集合中(PHP的hash table),而php_signale4最終會(huì)調(diào)用sigaction進(jìn)行底層的信號(hào)管理。

          配圖4 PHP如何優(yōu)雅的處理信號(hào).jpg

          這里我省略了大量代碼,將關(guān)鍵的點(diǎn)標(biāo)記了出來,其實(shí)PHP維護(hù)一個(gè)自己的信號(hào)集合,每當(dāng)調(diào)用 pcntl_signal_dispatch時(shí)就會(huì)查詢是否有信號(hào),上面的SIG_BLOCK會(huì)將信號(hào)阻塞,這樣只有我們把關(guān)鍵的代碼執(zhí)行完畢之后,再去觸發(fā)信號(hào)處理函數(shù)以保證數(shù)據(jù)和程序邏輯的完整性。

          PHP如何優(yōu)雅的處理信號(hào)

          經(jīng)常見到身邊的程序員們,每當(dāng)需要重啟PHP-FPM進(jìn)程的時(shí)候,使用的招數(shù)是kill掉所有PHP進(jìn)程,然后新啟動(dòng)。一般情況沒啥問題,但有些時(shí)候可能某個(gè)進(jìn)程的任務(wù)還沒執(zhí)行完,直接把人家中斷了略顯粗暴。

          其實(shí)只要你給PHP的Master進(jìn)程發(fā)送一條USR2信號(hào),它便會(huì)再處理完所有任務(wù)后,重啟子進(jìn)程,這才是所謂的優(yōu)雅。

          配圖5 PHP如何優(yōu)雅的處理信號(hào).jpg

          以上圖為例,如果我們想讓進(jìn)程優(yōu)雅退出的時(shí)候,只需要發(fā)送SIGTERM信號(hào)即可。需要注意的是SIGKILL和SIGSTOP信號(hào)會(huì)略過信號(hào)阻塞會(huì)將進(jìn)程直接停止,還有就是信號(hào)會(huì)中斷睡眠(SLEEP),sleep如果沒執(zhí)行完會(huì)返回剩下的秒數(shù)。

          信號(hào)相關(guān)的知識(shí)點(diǎn)其實(shí)有很多,還需要大家在平時(shí)的使用中繼續(xù)深入研究。以上就是這篇文章的全部?jī)?nèi)容,希望能對(duì)大家有所幫助。