1. 程式人生 > >php程序間通訊--訊號

php程序間通訊--訊號

php程序間通訊的另外一個手段就是通過 訊號 來在程序間傳遞資訊。訊號是一種系統呼叫。通常我們用的kill命令就是傳送某個訊號給某個程序的。具體有哪些訊號可以在liunx/mac中執行kill -l檢視。

一些php訊號的意思如下:

SIGHUP 終止程序     終端線路結束通話
SIGINT 終止程序     中斷程序
SIGQUIT 建立CORE檔案終止程序,並且生成core檔案
SIGILL 建立CORE檔案       非法指令
SIGTRAP 建立CORE檔案       跟蹤自陷
SIGBUS 建立CORE檔案       匯流排錯誤
SIGSEGV 建立CORE檔案        段非法錯誤
SIGFPE 建立CORE檔案       浮點異常
SIGIOT 建立CORE檔案        執行I/O自陷
SIGKILL 終止程序     殺死程序
SIGPIPE 終止程序      向一個沒有讀程序的管道寫資料
SIGALARM 終止程序     計時器到時
SIGTERM 終止程序      軟體終止訊號
SIGSTOP 停止程序     非終端來的停止訊號
SIGTSTP 停止程序      終端來的停止訊號
SIGCONT 忽略訊號     繼續執行一個停止的程序
SIGURG 忽略訊號      I/O緊急訊號
SIGIO 忽略訊號     描述符上可以進行I/O
SIGCHLD 忽略訊號      當子程序停止或退出時通知父程序
SIGTTOU

停止程序     後臺程序寫終端

SIGTTIN 停止程序      後臺程序讀終端
SIGXGPU 終止程序     CPU時限超時
SIGXFSZ 終止程序     檔案長度過長
SIGWINCH 忽略訊號     視窗大小發生變化
SIGPROF 終止程序     統計分佈圖用計時器到時      
SIGUSR1 終止程序     使用者定義訊號1                                     
SIGUSR2 終止程序     使用者定義訊號2                             
SIGVTALRM 終止程序      虛擬計時器到時


下面來看一個例子。啟動3個子程序,執行,父程序等待5秒鐘,向子程序傳送sigint訊號。子程序捕獲訊號,呼叫訊號處理函式處理。

<?php

$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}\n";

// 定義一個訊號處理函式
function sighandler($signo) {
    if( $signo == SIGINT ){
        $pid = getmypid();
        exit("{$pid} progress,oh no ,I'm killed!\n");
    }
}

//PHP < 5.3 使用
//配合pcntl_signal使用,表示每執行一條低階指令,就檢查一次訊號,如果檢測到註冊的訊號,就呼叫其訊號處理器。
//declare(ticks=1);

pcntl_signal( SIGINT, 'sighandler');  //註冊訊號處理函式
$childList = [];

for( $i = 0; $i < 3; $i++ ){
    $pid = pcntl_fork();
    if( $pid == 0 ){
        while( true ){
            //PHP >= 5.3
            //呼叫已安裝的訊號處理器
            //必須在迴圈裡呼叫,為了檢測是否有新的訊號等待dispatching。
            pcntl_signal_dispatch();

            echo "i am child " . getmypid() . " and i am running ! \n";
            $sec = rand(1,2);
            sleep($sec);
        }

    }else if( $pid == -1 ){
        exit("fork fail!" . PHP_EOL);
    }else{
        $childList[$pid] = 1;
    }
}

sleep(5);
foreach( $childList as $key=>$vo ){
    posix_kill( $key, SIGINT );  //觸發SIGINIT訊號
}
sleep(2);

echo  "($parentPid)parent is end " . PHP_EOL;

pcntl_signal_dispatch ( void )  
呼叫每個等待訊號通過pcntl_signal() 安裝的處理器。說明一下:pcntl_signal()函式僅僅是註冊訊號和它的處理方法,真正接收到訊號並呼叫其處理方法的是pcntl_signal_dispatch()函式必須在迴圈裡呼叫,為了檢測是否有新的訊號等待dispatching。

pcntl_signal_dispatch()這個函式是PHP5.3以上才支援的,如果你的PHP版本大於5.3,建議使用這個方法呼叫訊號處理器。5.3以下的版本需要在註冊訊號之前加一句:declare(ticks = 1);表示每執行一條低階指令,就檢查一次訊號,如果檢測到註冊的訊號,就呼叫其訊號處理器。