php有一組進程控制函數PCNTL,使得php能在*nix系統中實現跟c一樣的創建子進程、使用exec函數執行程序、處理信號等功能。
注意:pcntl這個擴展僅在cli/cgi模式下可用。mod_php和php-fpm中不可以使用。在web server環境中不要使用這組函數,因為會導致不可預料的結果。另,windows作為非類unix系統,沒有這些函數。
PCNTL 使用ticks來作為信號處理機制(signal handle callback mechanism),可以最小程度地降低處理異步事件時的負載。何謂ticks?Tick 是一個在代碼段中解釋器每執行 N 條低級語句就會發生的事件,這個代碼段需要通過declare來指定。
下面是一個隔5秒發送一個SIGALRM信號,并由signal_handler函數獲取,然后打印一個“Caught SIGALRM”的例子:
?php declare(ticks = 1); function signal_handler($signal) { print Caught SIGALRM/n pcntl_alarm(5); pcntl_signal(SIGALRM, signal_handler , true); pcntl_alarm(5); while(true){ ?
其實官方的pcntl_signal性能極差,主要是PHP的函數無法直接注冊到操作系統信號設置中,所以pcntl信號需要依賴tick機制來完成。 pcntl_signal的實現原理是,觸發信號后先將信號加入一個隊列中。然后在PHP的ticks回調函數中不斷檢查是否有信號,如果有信號就執行PHP中指定的回調函數,如果沒有則跳出函數。 ticks=1表示每執行1行PHP代碼就回調此函數。實際上大部分時間都沒有信號產生,但ticks的函數一直會執行。 比較好的做法是去掉ticks,轉而使用pcntl_signal_dispatch,在代碼循環中自行處理信號。
pcntl_signal_dispatch的實現?php// 定義一個處理器,接收到SIGINT信號后只輸出一行信息function signalHandler($signo) { switch ($signo) { case SIGUSR1: echo SIGUSR1/n break; case SIGUSR2: echo SIGUSR2/n break; default: echo unknow break;//安裝信號觸發器器pcntl_signal(SIGINT, signalHandler while (true) { sleep(1); posix_kill(posix_getpid(), SIGUSR1);///向當前進程發送SIGUSR1信號 pcntl_signal_dispatch(); //接收到信號時,調用注冊的signalHandler()}PCNTL的函數:信號處理
int pcntl_alarm ( int $seconds )
設置一個$seconds秒后發送SIGALRM信號的計數器
bool pcntl_signal(int $signo ,callback $handler [,bool $restart_syscalls=true])
為$signo設置一個處理該信號的回調函數
第一個參數是信號編號 第二個參數是信號發生時回調的html' target='_blank'>PHP函數。 第三個參數是是否restart,是否重新注冊此信號。這個參數如果為false,那此信號只注冊處理一次。
注意:每次對 pcntl_alarm()的調用都會取消之前設置的alarm信號和sleep()函數。
下面是一個隔5秒發送一個SIGALRM信號,并由signal_handler函數獲取,然后打印一個“Caught SIGALRM”的例子:
?php declare(ticks = 1); function signal_handler($signal) { print Caught SIGALRM/n pcntl_alarm(5); pcntl_signal(SIGALRM, signal_handler , true); pcntl_alarm(5); for(;;) { ?執行程序
void pcntl_exec ( string $path [, array $args [, array $envs ]] )
在當前的進程空間中執行指定程序,類似于c中的exec族函數。所謂當前空間,即載入指定程序的代碼覆蓋掉當前進程的空間,執行完該程序進程即結束。
?php $dir = /home/test/ $cmd = ls $option = -l $pathtobin = /bin/ls $arg = array($cmd, $option, $dir); pcntl_exec($pathtobin, $arg); echo 123 //不會執行到該行 ?創建進程
int pcntl_fork ( void ) 為當前進程創建一個子進程int pcntl_wait ( int $status [, int $options ] ) 阻塞當前進程,只到當前進程的一個子進程退出或者收到一個結束當前進程的信號。 int pcntl_waitpid ( int $pid , int $status [, int $options ] ) 功能同pcntl_wait,區別為waitpid為等待指定pid的子進程。當pid為-1時pcntl_waitpid與pcntl_wait一樣。
在 pcntl_wait和pcntl_waitpid兩個函數中的$status中存了子進程的狀態信息,這個參數可以用于 pcntl_wifexited、pcntl_wifstopped、pcntl_wifsignaled、pcntl_wexitstatus、 pcntl_wtermsig、pcntl_wstopsig、pcntl_waitpid這些函數。
舉個例子
?php $pid = pcntl_fork(); if($pid) { pcntl_wait($status); $id = getmypid(); echo parent process,pid {$id}, child pid {$pid}/n } else { $id = getmypid(); echo child process,pid {$id}/n sleep(2); ?
子進程在輸出child process等字樣之后sleep了2秒才結束,而父進程阻塞著直到子進程退出之后才繼續運行。
進程優先級int pcntl_getpriority ([ int $pid [, int $process_identifier ]] ) 取得進程的優先級,即nice值,默認為0。不同的系統類型以及內核版本下 優先級可能不同(手冊中為-20到20)bool pcntl_setpriority ( int $priority [, int $pid [, int $process_identifier ]] ) 設置進程的優先級
以上就是php如何處理進程信號(附實例)的詳細內容,PHP教程
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答