Please note that you must use bitwise OR | in the following:
"The value of options is the value of zero or more of the following two global constants OR'ed together"
i.e.
WNOHANG | WUNTRACED
pcntl_waitpid
(PHP 4 >= 4.1.0, PHP 5)
pcntl_waitpid — 等待或返回fork的子进程状态
说明
$pid
, int &$status
[, int $options = 0
] )
挂起当前进程的执行直到参数pid指定的进程号的进程退出,
或接收到一个信号要求中断当前进程或调用一个信号处理函数。
如果pid指定的子进程在此函数调用时已经退出(俗称僵尸进程),此函数
将立刻返回。关于waitpid更详细的规范请参见您系统的waitpid(2)手册。
参数
-
pid -
参数
pid的值可以是以下之一:pid可选值< -1 等待任意进程组ID等于参数 pid给定值的绝对值的进程。-1 等待任意子进程;与pcntl_wait函数行为一致。 0 等待任意与调用进程组ID相同的子进程。 > 0 等待进程号等于参数 pid值的子进程。Note:
指定-1作为
pid的值等同于pcntl_wait() 提供(负的options)。 -
status -
pcntl_waitpid()将会存储状态信息到
status参数上,这个通过status参数返回的状态信息可以用以下函数 pcntl_wifexited(), pcntl_wifstopped(), pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig()以及 pcntl_wstopsig()获取其具体的值。 -
options -
如果您的操作系统(多数BSD类系统)允许使用wait3,您可以提供可选的
options参数。如果这个参数没有提供,wait将会被用作系统调用。如果wait3不可用,提供参数options不会有任何效果。options的值可以是0 或者以下两个常量或两个常量“或运算”结果(即两个常量代表意义都有效)。options可用的值WNOHANG 如果没有子进程退出立刻返回。 WUNTRACED 子进程已经退出并且其状态未报告时返回。
返回值
pcntl_waitpid()返回退出的子进程进程号,发生错误时返回-1,如果提供了
WNOHANG作为option(wait3可用的系统)并且没有可用子进程时返回0。
参见
- pcntl_fork() - 在当前进程当前位置产生分支(子进程)。译注:fork是创建了一个子进程,父进程和子进程 都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程 号,而子进程得到的是0。
- pcntl_signal() - 安装一个信号处理器
- pcntl_wifexited() - 检查状态代码是否代表一个正常的退出。
- pcntl_wifstopped() - 检查子进程当前是否已经停止
- pcntl_wifsignaled() - 检查子进程状态码是否代表由于某个信号而中断
- pcntl_wexitstatus() - 返回一个中断的子进程的返回代码
- pcntl_wtermsig() - 返回导致子进程中断的信号
- pcntl_wstopsig() - 返回导致子进程停止的信号
A better way to do this and not end up having zombie processes until all child processes ends is like this:
<?php
$i = 0;
$starttime = microtime(TRUE);
$pid_arr = array();
while ($i < intval($argv[1]))
{
$pid = pcntl_fork();
if ($pid == -1)
{
die('could not fork');
}
else
{
if ($pid) // parent
{
$pid_arr[$i] = $pid;
}
else // child
{
performSomeFunction($i+1);
}
}
$i++;
}
while(count($pid_arr) > 0)
{
$myId = pcntl_waitpid(-1, $status, WNOHANG);
foreach($pid_arr as $key => $pid)
{
if($myId == $pid) unset($pid_arr[$key]);
}
usleep(100);
}
$elapsed = microtime(TRUE) - $starttime;
print "\n==> total elapsed: " . sprintf("%f secs.\n", $elapsed);
?>
please note, if you using configure option --enable-sigchild(Enable PHP's own SIGCHLD handler) when complie php(under linux 2.6.18-53.1.13.el5.centos.plus and php 5.2.5 as I know), pcntl_waitpid and pcntl_wait in php script would never return the child pid, because the build in handle get it first.
---
while ($i < intval($argv[1]))
{
$pid = pcntl_fork();
if ($pid == -1)
{
die('could not fork');
}
else
{
if ($pid) // parent
{
$pid_arr[$i] = $pid;
}
else // child
{
performSomeFunction($i+1);
}
}
$i++;
}
---
careful, this will create a lot more children than you probably expect. You must return or exit after performSomeFunction($i+1); ie,
else // child
{
performSomeFunction($i+1);
exit(0);
}
Here's a decent example of the pcntl_waitpid() call:
$i = 0;
$starttime = microtime(TRUE);
$pid_arr = array();
while ($i < intval($argv[1]))
{
$pid = pcntl_fork();
if ($pid == -1)
{
die('could not fork');
}
else
{
if ($pid) // parent
{
$pid_arr[$i] = $pid;
}
else // child
{
performSomeFunction($i+1);
}
}
$i++;
}
foreach ($pid_arr as $pid)
{
// we are the parent
pcntl_waitpid($pid, $status);
}
$elapsed = microtime(TRUE) - $starttime;
print "\n==> total elapsed: " . sprintf("%f secs.\n", $elapsed);
