php多行程編程 PHP的行程控制支持實作了Unix方式的行程創建, 程式執行, 信號處理以及行程的中斷, 行程控制不能被應用在Web服務器環境,當其被用于Web服務環境時可能會帶來意外的結果, pcntl函式
- pcntl_fork():在當前行程當前位置產生分支(子行程),譯注:fork是創建了一個子行程,父行程和子行程 都從fork的位置開始向下繼續執行,不同的是父行程執行程序中,得到的fork回傳值為子行程 號,而子行程得到的是0
<?php $pid = pcntl_fork(); //父行程和子行程都會執行下面代碼 if ($pid == -1) { //錯誤處理:創建子行程失敗時回傳-1. die('could not fork'); } else if ($pid) { //父行程會得到子行程號,所以這里是父行程執行的邏輯 pcntl_wait($status); //等待子行程中斷,防止子行程成為僵尸行程, } else { //子行程得到的$pid為0, 所以這里是子行程執行的邏輯, exit();//子行程執行完后應該退出,不然會繼續執行后面的邏輯 }
- pcntl_wait(int &$status[, int $options = 0]):等待或回傳fork的子行程狀態,相當于pcntl_waitpid(-1,int &$status[,int $options = 0])
- pcntl_waitpid(int $pid , int &$status[,int $options = 0]) $status是作為一下函式的引數
- pcntl_wifexited(int $status) 檢查子行程狀態代碼是否代表正常退出,
- pcntl_wexistatus(int $status) 回傳一個中斷的子行程回傳代碼,僅在正常中斷才有效
- pcntl_wifsignaled(int $status) 檢查子行程是否由某個未捕獲的信號退出的,是回傳true,否回傳false
- pcntl_wtermsig(int $status)回傳導致子行程中斷的信號,當pcntl_wifsignaled回傳true時有效
<?php echo "主行程\n"; $pid = pcntl_fork(); //父行程和子行程都會執行這些代碼 if($pid == -1 ){ //創建子行程失敗會回傳-1 throw new Exception ('fork error on Task object'); }else if($pid){ //創建成功會父行程會得到子行程的pid echo "等待子行程執行"; pcntl_wait($status);//等待子行程中斷 echo "子行程執行狀態:"; echo "是否正常退出:",pcntl_wifexited($status),"\n"; echo "子行程回傳的代碼:",pcntl_wexitstatus($status),"\n";//僅在pcntl_wifexited回傳true時生效,只能是int,輸出123 echo "子行程是否是由于某個未捕獲的信號退出的:",pcntl_wifsignaled($status),"\n";//如果是kill -9|-15 殺死的行程回傳true echo "導致子行程中斷的信號:",pcntl_wtermsig($status),"\n"; 輸出 9 | 15 var_dump($status); }else{ //創建成功子行程會得到pid=0 sleep(2); echo "子行程執行完畢\n"; exit(123) }
- pcntl_alarm(int $seconds):為行程設定一個alarn鬧鐘信號
- pcntl_signal(int $signo, callback $handler [, bool $restart_syscalls = true ] )為指定的信號安裝一個新的信號處理器
- pcntl_signal_get_handler(int $signo) 獲取指定信號的處理函式
<?php echo "設定3秒之后發送鬧鐘信號\n"; pcntl_alarm(3); function dealSigalarm(){ echo "收到信號 SIGALRM \n退出程式,,,\n"; exit(); } echo "安裝信號處理器\n"; pcntl_signal(SIGALRM,"dealSigalarm");//對于不能被阻塞、處理和忽略的信號,php為這些事件注冊信號處理函式會產生一個致命錯誤 SIGSTOP,SIGKILL var_dump(pcntl_signal_get_handler(SIGUSR1));//輸出dealSigalarm pcntl_signal(SIGUSR1,function(){ echo "收到用戶自定義信號\n"; }); $i = 1; while(1){ sleep(1); echo $i++,"\n"; echo "分發... \n"; pcntl_signal_dispatch(); };
- pcntl_getpriority( int $pid = getmypid() [, int $process_identifier = PRIO_PROCESS ])獲取行程的優先級
- pcntl_setpriority( int $priority [ , int $pid = getmypid() [, int $process_identifier = PRIO_PROCESS]])設定行程的優先級
- getmypid() 獲取當前php行程的pid
- posix_getpid() 獲取當前行程的pid
<?php /** * php行程的優先級 */ for($i = 1;$i<=5;$i++){ $pid = pcntl_fork(); if($pid == -1){ throw new Exception("fork error on task object"); }else if ($pid){ pcntl_wait($status); }else{ $end_time = time()+3; $k = 0; while(time()<=$end_time){ $k++; } $pid = getmypid(); echo "當前行程id:".$pid,"優先級:",pcntl_getpriority($pid); pcntl_setpriority($i); echo "修改之后的優先級為:",pcntl_getpriority(),"\n"; echo "執行了行程{$i} {$k}次\r\n"; exit(); } }
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/84980.html
標籤:PHP
