首頁  >  文章  >  後端開發  >  如何使用PHP中pcntl和libevent實現Timer功能

如何使用PHP中pcntl和libevent實現Timer功能

不言
不言原創
2018-06-15 15:28:451681瀏覽

PHP 中實作Timer功能,中間使用到了php多線程,本文給出來pcntl的解釋。

PHP 使用pcntl和libevent 實作Timer功能,先看例子,pcntl(PHP執行緒)解釋在下面。

<?php  
function newChild($func_name) {  
    echo "enter newChild\n";  
    $args = func_get_args();  
    unset($args[0]);  
    $pid =  pcntl_fork();  
    if ($pid == 0) {  
        function_exists($func_name) and exit(call_user_func_array($func_name, $args)) or exit(-1);  
    } else if($pid == -1) {  
        echo "Couldn&#39;t create child process";  
    } else {  
        return $pid;  
    }  
}  
(PS:^_^不错的php开发交流群:256271784,验证:csl,有兴趣的话可以加入进来一起讨论)
function on_timer() {  
    echo "timer called\n";  
}  
   
/** 
 * @param $func string, function name 
 * @param $timeouts int, microtimes for time delay 
 */ 
function timer($func, $timeouts){  
   
    echo "enter timer\n";  
    $base = event_base_new();  
    $event = event_new();  
   
    event_set($event, 0, EV_TIMEOUT, $func);  
    event_base_set($event, $base);  
    event_add($event, $timeouts);  
   
    event_base_loop($base);  
}  
   
$pid = newChild("timer", "on_timer", 5000000);  
   
if ($pid > 0) {  
    echo "master process exit\n";  
}

PHP 擴展pcntl 實現” 多線程”( 進程)
pcntl 與ticks
ticks 是透過declare(ticks = n) {statement} 語法定義的, declare 語法目前只能接受ticks, 他定義的ticks = n 的意義是當declare 指定的語句區塊中執行了N 條低階語句去發生一個事件, 這個事件可以透過register_tick_function($function_name) 來註冊.
pcntl 的訊號機制是基於ticks 機制實現的. 因此, 我們使用pcntl 族函數中信號相關的函數時, 需要在前面增加declare(ticks = n) 語法結構.
int pcntl_alarm(int $seconds):
$seconds 秒後向進程發送一個SIGALRM 訊號, 每次呼叫pcntl_alarm 方法都會取消先前設定的時脈.
void pcntl_exec(string $path[, array $args[, array $env]]):
在目前行程空間執行程式.
$path: 必須是二進位執行檔, 或具有有效腳本頭資訊(#!/usr/local/bin/php) 的腳本檔路徑.
$args: 將要傳遞給該程式的字串參數列表( 數組形式)
$envs: 環境變數. 以數組(key => value 形式) 方式傳遞給要執行程式的環境變數.
int pcntl_for k (void):
建立一個子進程, 該子進程與父進程只是PID( 進程號) 和PPID( 父進程號) 不同.
在父線程執行時返回創建的子進程pid, 在子線程執行時返回0, 創建子進程失敗時會在父進程上下文返回-1, 並引發php 錯誤.
理解這裡的fork 需要知道: pcntl_fork 創建的是一個分支節點, 相當於一個標記, 父進程完成後, 子進程會從標記處繼續執行, 也就是說pcntl_fork 後面的程式碼分別被父進程和子進程執行了兩遍, 而兩個進程在執行過程中得到的返回值是不同的. 因此, 才可以分離父子進程執行不同的代碼.
int pcntl_getpriority([int $pid = getmypid()[, int $process_identifier = PRIO_PROCESS]]):
取得給定$pid 對應的程序的優先權, 預設是透過getmypid() 取得到的值也就是目前進程.
$pid: 如果沒有指定, 預設是當前進程.
$process_identifier: PRIO_PGRP, PRIO_USER, PRIO_PROCESS 三者之一, 預設PRIO_PROCESS. 其中PRIO_PGRP 指取得進程組的優先權, PRIO_USER 指標取得使用者行程的優先權, PRIO_PROCESS 指取得特定行程優先權.
傳回行程的優先權, 或在發生錯誤時傳回false, 值越小說明越優先
bool pcntl_setpriority(int $priority[, int $pid = getmypid()[, int $process_identifier = PRIO_PROCESS]]:
設定行程的優先權.
$priority: 優先權值, -20 到20 的範圍內, 預設優先權為0.   值為越小說明越優先.
$pid: 如果沒有指定, 指當前程序
$process_identifier: 意義同pcntl_getpriority 的$process_identifier.
設定成功回傳TRUE, 失敗回傳FALSE.
bool pcntl_signal_dispatch(signal_dispatch( void):
呼叫透過pcntl_signal() 安裝的即將發生的訊號的處理器.
呼叫成功返回TRUE,失敗回傳false.
php 5.3.3 加入
bool pcntl_signal(int $signo , callback $handler[, bool $restart_syscalls = true]):
為指定的訊號$signo 安裝一個新的訊號處理器$handler.
最後一個參數不明白意義.
bool pcntl_sigprocmask(int $how, array $set[, array &$oldset]):
增加, 刪除或設定鎖定訊號, 特定的行為依賴於$how 參數
$how: SIG_BLOCK 用於將訊號增加到目前鎖定訊號中, SIG_UNBLOCK 用於把訊號從目前鎖定訊號移除, SIG_SETMASK 用於用給定的訊號清單取代目前鎖定訊號.
$set: 要增加, 移除或設定的訊號清單.
$ oldset: 用於向呼叫者傳回舊的鎖定訊號.
成功傳回TRUE, 失敗回傳FALSE.
int pcntl_sigtimedwait(array $set[, array &$siginfo[, int $seconds = 0[, ​​int $ nanoseconds = 0]]]):
pcntl_sigtimedwait 實際上和pcntl_sigwaitinfo() 所做的是同樣的事情, 不過pcntl_sigtimedwait 多了兩個增強的參數$seconds 和$nanoseconds, 這樣就允許腳本的停留時間有一個上限而不是無限制等待.
$set: 需要等待的信號列表
$siginfo: 用來向調用者返回等待得到的信號的信息, 信息內容見pcntl_sigwaitinfo
#$seconds: 超時的秒數
$nanoseconds: 超時的奈秒數
成功後, pcntl_sigtimedwiat() 傳回訊號編號
int pcntl_sigwaitinfo(array $set[, array &$siginfo]):
掛起目前腳本的執行, 直到接受到$set 中的某個訊號, 如果其中的一個訊號將要到達( 例如被pcntl_sigprocmask 鎖定) 那麼用來向呼叫者回傳等待得到的訊號的資訊, 此資訊包含以下內容:
1.       所有訊號所包含以下三個資訊:##a)        signo: 訊號編號
b)        signo: 訊號編號##b)        signo: 訊號編號# : ##c)         code: 訊號代碼
2.       SIGCHLD 訊號特有的資訊
a)        記憶  stime: 系統消耗時間
d)        pid: 發送進程id
e)        uid: 傳送程序的真實使用者id
3.       SIGILL #4.       SIGPOLL 獨特的資訊:
a)        band: band event, 意義未知
#b)        fd:2102_$D
b)        fd:2102_$poffffpfpffpfpfpfpfpfpfpfp

掛起當前程序直到一個子程序退出或直到一個信號要求終止當前進程或調用一個信號處理函數. 如果子進程在調用時已經退出( 俗稱成為了殭屍進程), 此函數會馬上回傳, 所有的系統資源都將被釋放.
$status 用來保存子進程的狀態資訊, 此狀態資訊由下列函數產生: pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wexitstatus, pcntlms, pcntlms,p .
$options: 如果你的系統允許wait3( 大多數的BSD 類別系統), 你可以提供一個可選的options 參數, 如果不提​​供這個參數, wait 將會使用系統呼叫, 如果系統不允許wait3 , 提供這個參數不會有任何影響, $options 的值可以是0 或WNOHANG 和WUNTRACED 兩個常數.
函數返回退出的子進程的PID, 或在錯誤時返回-1, 或者如果提供WNOHANG 作為option(wait3 不可用的系統) 並且無有效子程序返回0
殭屍進程: 由於父進程在fork 之後, 無法預知子進程什麼時候結束, 所以子進程為了要留給父進程一些信息, 會留下一個稱作殭屍的資料結構, 等待由父進程發起wait 的操作來為它收屍, 在子進程結束( 邏輯結束) 到父進程收屍前這段時間子進程就被稱為殭屍進程, 在父進程結束後, 所有的子程序會交由Init 來負責, 因此, 如果父進程結束, 殭屍進程都會被回收, 但是, 如果父進程永遠不結束, 這些殭屍進程就一直佔用進程號, 如果系統進程號耗盡, 那麼將導致無法啟動新進程, 因此, 安全的做法是在父進程中為自己產生的子進程去收屍.
int pcntl_waitpid(int $pid, int &$status[, int $options = 0 ]):
掛起當前進程直到給定$pid 的子進程退出, 或者當前進程接受到一個退出信號, 或者接受到一ige 信號去調用一個信號處理器.
如果給定$pid對應的子程序在呼叫此函數時已經退出( 殭屍態), 函數立刻返回, 所有的系統資源被釋放.
$pid: 進程號, 小於-1 表明等待的是進程組中的任何子進程, 進程組號就是$pid 的絕對值. 等於-1 表示等待任意紫禁城, 與pcntl_wait 函數行為一致. 等於0 代表等待與調用進程在同一組的子進程, 大於0 代表是特定的進程.
$status: 用來由函數傳回子進程狀態. 此狀態資訊由下列函數產生: pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig.##cxitoptions:ffpfpfid未來#ffpffp未來的意義> (int $status):
傳回一個已中斷的子程序回傳代碼, 此函數僅在pcntl_wifexited 函數傳回TRUE 時有用.
$status 參數是pcntl_waitpid 產生的狀態資訊.
bool pcntl_wifexited(int $status):
檢查給定狀態是否表明子進程是正常退出的.
bool pcntl_wifsignaled(int $status):
檢查給定狀態是否表明子進程是由於收到某個信號退出的.
bool pcntl_wifstopped(int $status):
檢查$status 是否能表明子進程當前已經停止, 這個函數只有在作用於pcntl_waitpid 函數使用的WUNTRACED 作為$options 參數的值時產生的$status上才有效.
int pcntl_wstopsig(int $status):
透過分析$status 返回使得子程序停止的信號的編號, 這個函數只有在pcntl_wifsignaled 返回TRUE 時才有效.
int pcntl_wtermsig(int $status):
返回讓進程中斷的訊號編號. 這個函數只有在pcntl_wifsignaled 返回TRUE 時才有效.

以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!

相關推薦:


PHP取整函數之ceil,floor,round,intval的區別解析

如何使用PHP中curl模擬post上傳及接收檔案

#########################################

以上是如何使用PHP中pcntl和libevent實現Timer功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn