php多进程有什么用,有关php多进程的用法举例
在php中實現(xiàn)多進(jìn)程,一般有兩種方法,一種是使用PHP自帶的pcntl_*函數(shù)(僅限linux),另一種就是使用popen/proc_open,然后在php內(nèi)部控制進(jìn)程數(shù)量。
使用pcntl_*函數(shù)
PHP提供了一系列的pcntl_*函數(shù),顧名思義就是process control functions,專門用來管理進(jìn)程的。最常用的就是pcntl_fork和pcntl_wait。
pcntl_fork的作用就是從當(dāng)前的進(jìn)程再派生出一個子進(jìn)程。pcntl_wait的作用是掛起當(dāng)前進(jìn)程,直到一個子進(jìn)程中止。
例子:
復(fù)制代碼 代碼示例:
//配合pcntl_signal使用
declare(ticks=1);
//最大的子進(jìn)程數(shù)量
$max = 5;
//當(dāng)前的子進(jìn)程數(shù)量
$child = 0;
//當(dāng)子進(jìn)程退出時,會觸發(fā)該函數(shù)
function sig_handler($sig) {
global $child;
switch($sig) {
case SIGCHLD:
echo 'SIGCHLD received'."\n";
$child--;
}
}
//注冊子進(jìn)程退出時調(diào)用的函數(shù)
pcntl_signal(SIGCHLD, "sig_handler");
while(true) {
$child++;
/**
* 這個函數(shù)會返回兩個值,一個為0,表示子進(jìn)程;一個為正整數(shù)表示子進(jìn)程的id
* 所以if和else里的兩段代碼都會執(zhí)行
* if里的代碼是父進(jìn)程執(zhí)行的
* else里的代碼是子進(jìn)程執(zhí)行的
*/
$pid = pcntl_fork();
if ($pid) {
//這里是父進(jìn)程執(zhí)行的代碼
//如果子進(jìn)程數(shù)超過了最大值,則掛起父進(jìn)程
//也就是說while語句不會繼續(xù)執(zhí)行
if ($child >= $max) {
pcntl_wait($status);
}
}
else {
//這里是子進(jìn)程執(zhí)行的代碼
//如果要執(zhí)行其他命令的話,使用pcntl_exec
echo "starting new child | now we have $child child process\n";
sleep(rand(3, 5));
exit;
}
}
?>
上面這段代碼就是保證有5個子進(jìn)程一直在干活,如果$child數(shù)量大于$max,就等子進(jìn)程結(jié)束后再繼續(xù)運(yùn)行。子進(jìn)程結(jié)束后會調(diào)用 sig_handler函數(shù),sig_handler會將$child
數(shù)量減1,那邊while繼續(xù)執(zhí)行。
使用popen/proc_open
popen會創(chuàng)建一個管道來連接該進(jìn)程,然后使用fread/fgets/stream_get_contents來讀取該進(jìn)程返回的結(jié)果。跟 exec或system之類的函數(shù)不同的是,exec會等待命令執(zhí)行完
成,再運(yùn)行下面的代碼,但popen不會。proc_open又更加強(qiáng)大一些,支持 stdin和stdout,路徑設(shè)置等等。
因為這些函數(shù)只負(fù)責(zé)創(chuàng)建,沒有相應(yīng)的管理方法,所以只能在PHP文件內(nèi)部自己來實現(xiàn)。
演示示例:(PHP多進(jìn)程并發(fā)控制的測試實例)
復(fù)制代碼 代碼示例:
function run($input)
{
global $p_number;
if ($p_number <= 0)
{
$p_number = worker_processes($p_number);
}
$p_number = $p_number - 1;
$out = popen("/bin/sh /opt/zhangyan.sh \"{$input}\" &", "r");
pclose($out);
}
function worker_processes($p_number)
{
$limit = 500;//允許推到后臺的最大進(jìn)程數(shù)
while ($p_number <= 0)
{
$cmd = popen("ps -ef | grep \"/opt/zhangyan.sh\" | grep -v grep | wc -l", "r");
$line = fread($cmd, 512);
pclose($cmd);
$p_number = $limit - $line;
if ($p_number <= 0)
{
sleep(1);//暫停1秒鐘
}
}
return $p_number;
}
$input = "http://www.jbxue.com"; //模擬從隊列文件中讀取到的數(shù)據(jù)
for ($i = 1; $i <= 1000; $i++)
{
run($input);
echo "Idle process number: " . $p_number . "\n";
}
?>
代碼說明:
1. 設(shè)置/opt/zhangyan.php最多允許生成500個子進(jìn)程;
2. 當(dāng)/opt/zhangyan.php讀取到一條數(shù)據(jù)后,將允許生成的子進(jìn)程數(shù)減1(空閑進(jìn)程數(shù)$p_number=500-1=499),然后將數(shù)據(jù)交給/opt/zhangyan.sh去后臺處理,不等待
/opt/zhangyan.sh處理結(jié)束,繼續(xù)讀取下一條數(shù)據(jù);
3. 當(dāng)允許生成的子進(jìn)程數(shù)減至0時(空閑進(jìn)程數(shù)$p_number=0),/opt/zhangyan.php會等待1秒鐘,然后檢查后臺還有多少個/opt /zhangyan.sh子進(jìn)程尚未處理結(jié)束;
4. 如果1秒鐘之后/opt/zhangyan.php發(fā)現(xiàn)后臺的/opt /zhangyan.sh子進(jìn)程數(shù)還是500(空閑進(jìn)程數(shù)$p_number=0),會繼續(xù)等待1秒鐘,如此反復(fù);
5. 如果/opt /zhangyan.php發(fā)現(xiàn)后臺尚未處理結(jié)束的/opt/zhangyan.sh子進(jìn)程數(shù)減少到300個了(空閑進(jìn)程數(shù)$p_number=500-300=200),那么/opt/zhangyan.php會再往后臺
推送200個/opt/zhangyan.sh子進(jìn)程;
建議使用pcntl_*系函數(shù)更方便一些,邏輯更清楚。
總結(jié)
以上是生活随笔為你收集整理的php多进程有什么用,有关php多进程的用法举例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php判断端口跳转,PHP判断端口是否打
- 下一篇: matlab应用大全二手,MATLAB应