php 中的訊號處理操作例項詳解
本文例項講述了php 中的訊號處理操作。分享給大家供大家參考,具體如下:
首先我們需要了解幾個函式
pcntl_signal 安裝訊號處理器,也就是當指定訊號發生時,呼叫函式。
pcntl_alarm 指定秒數後向程序傳送SIGALRM訊號。
posix_getpid 返回當前程序id
posix_kill 給指定程序傳送訊號
一些常用的訊號說明
SIGHUP
本訊號在使用者終端連線(正常或非正常)結束時發出,通常是在終端的控制程序結束時,
通知同一session內的各個作業,這時它們與控制終端不再關聯。
SIGINT
程式終止(interrupt)訊號,在使用者鍵入INTR字元(通常是Ctrl-C)時發出。
SIGQUIT
和SIGINT類似,但由QUIT字元(通常是Ctrl-/)來控制;程序在因收到SIGQUIT退出時會產生core檔案,
在這個意義上類似於一個程式錯誤訊號。
SIGKILL
用來立即結束程式的執行。本訊號不能被阻塞、處理和忽略。如果管理員發現某個程序終止不了,可嘗試傳送這個訊號。
SIGTERM
程式結束(terminate)訊號,與SIGKILL不同的是該訊號可以被阻塞和處理。通常用來要求程式自己正常退出,
shell命令kill預設產生這個訊號。如果程序終止不了,我們才會嘗試SIGKILL。
SIGUSR1
留給使用者使用
SIGUSR2
留給使用者使用
SIGALRM
時鐘定時訊號,計算的是實際的時間或時鐘時間。alarm函式使用該訊號。
SIGCHLD
子程序結束時,父程序會收到這個訊號。
例1:
<?php declare(ticks = 1); //訊號處理函式 function sig_func() { echo "child exit \r\n"; } //設定訊號處理器 pcntl_signal(SIGCHLD,'sig_func'); $pid = pcntl_fork(); if($pid == -1) { die('fork error'); } else if ($pid) { pcntl_wait($status); } else { echo "child... \r\n"; exit; }
當子程序退出時,會向父程序傳送SIGCHLD訊號,我們通過設定訊號處理器,成功的處理訊號。
例2:
<?php declare(ticks = 1); //訊號處理函式 function sig_func($signo) { switch($signo) { case SIGCHLD: { echo "child SIGCHLD \r\n"; break; } case SIGTERM: { echo "child SIGTERM \r\n"; break; } default: //處理所有其他訊號 break; } } //設定訊號處理器 pcntl_signal(SIGCHLD,'sig_func'); //設定訊號處理器 pcntl_signal(SIGTERM,'sig_func'); $pid = pcntl_fork(); if($pid == -1) { die('fork error'); } else if ($pid) { pcntl_wait($status); } else { sleep(3); echo "child \r\n"; sleep(3); posix_kill(getmypid(),SIGTERM); exit; }
父程序等待子程序的退出,子程序等待3秒後輸出child,再等待3秒後向自身傳送結束程式訊號。
例3:
<?php declare(ticks = 1); //訊號處理函式 function sig_func($signo) { switch($signo) { case SIGCHLD: { echo "child SIGCHLD \r\n"; break; } /*這裡要把處理SIGTERM訊號的程式碼註釋掉 case SIGTERM: { echo "child SIGTERM \r\n"; break; }*/ default: //處理所有其他訊號 break; } } //設定訊號處理器 pcntl_signal(SIGCHLD,'sig_func'); //設定訊號處理器,也註釋掉 //不然當父程序發向子程序傳送SIGTERM訊號時,子程序不會退出,還會繼續執行 //我們的訊號處理函式把SIGTERM給忽略了 //pcntl_signal(SIGTERM,'sig_func'); $pid = pcntl_fork(); if($pid == -1) { die('fork error'); } else if ($pid) { sleep(30); posix_kill($pid,SIGTERM); } else { $cnt = 0; for(;;) { sleep(3); echo $cnt,'-'; ++$cnt; } exit; }
父程序在等待30秒後,向子程序傳送SIGTERM結束程式訊號。如果我們設定了SIGTERM訊號的處理器,並且在自定義訊號處理器中並沒有殺死該程序,則該子程序會一直執行下去。
pcntl_signal()函式僅僅是註冊訊號和它的處理方法,真正接收到訊號並呼叫其處理方法的是pcntl_signal_dispatch()函式。
例4:
<?php //使用ticks需要PHP 4.3.0以上版本 //declare(ticks = 1); function sig_func() { echo "SIGALRM \r\n"; } //設定訊號處理器 pcntl_signal(SIGALRM,'sig_func'); pcntl_alarm(3);
通過函式pcntl_alarm()3秒後給程序傳送SIGALRM訊號,但訊號處理函式並未呼叫。
原因是我們註釋了declare(ticks = 1);這段程式碼,而又沒有呼叫pcntl_signal_dispatch()函式。
declare(ticks = 1);表示每執行一條低階指令,就檢查一次訊號,如果檢測到註冊的訊號,就呼叫其訊號處理器。但是這種處理方式效率很低,建議在程式碼迴圈中通過pcntl_signal_dispatch()來處理訊號。
<?php //使用ticks需要PHP 4.3.0以上版本 //declare(ticks = 1); function sig_func() { echo "SIGALRM \r\n"; } //設定訊號處理器 pcntl_signal(SIGALRM,'sig_func'); pcntl_alarm(3); //因為3秒後pcntl_alarm函式才會給程序傳送SIGALRM訊號 //所以我們通過sleep函式等待3秒後,呼叫pcntl_signal_dispatch()來處理訊號 sleep(3); pcntl_signal_dispatch();
pcntl_signal_dispatch()這個函式是PHP5.3以上才支援的,如果你的PHP版本大於5.3,建議使用這個方法呼叫訊號處理器。
5.3以下的版本需要在註冊訊號之前加上:declare(ticks = 1);
更多關於PHP相關內容感興趣的讀者可檢視本站專題:《PHP程序與執行緒操作技巧總結》、《PHP網路程式設計技巧總結》、《PHP基本語法入門教程》、《PHP陣列(Array)操作技巧大全》、《php字串(string)用法總結》、《php+mysql資料庫操作入門教程》及《php常見資料庫操作技巧彙總》
希望本文所述對大家PHP程式設計有所幫助。