请注意,如果您在编译php时使用配置选项 --enable-sigchild(启用PHP自己的SIGCHLD处理程序)(在我的情况下,使用linux 2.6.18-53.1.13.el5.centos.plus和php 5.2.5),则php脚本中的pcntl_waitpid和pcntl_wait将永远不会返回子进程pid,因为内置的句柄会先获取它。
(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)
pcntl_waitpid — 等待或返回已派生子进程的状态
挂起当前进程的执行,直到由process_id
参数指定的子进程退出,或者直到传递一个信号,其操作是终止当前进程或调用信号处理函数。
如果在调用时由process_id
请求的子进程已经退出(所谓的“僵尸”进程),则函数立即返回。子进程使用的任何系统资源都将被释放。请参阅您系统的waitpid(2)手册页,了解waitpid在您系统上的具体工作方式。
process_id
process_id
的值可以是以下之一
< -1 |
等待任何其进程组ID等于process_id 绝对值的子进程。 |
-1 |
等待任何子进程;这与wait函数的行为相同。 |
0 |
等待任何其进程组ID等于调用进程的进程组ID的子进程。 |
> 0 |
等待进程ID等于process_id 值的子进程。 |
注意:
将
-1
指定为process_id
等效于pcntl_wait()提供的功能(减去flags
)。
status
pcntl_waitpid() 将状态信息存储在status
参数中,可以使用以下函数对其进行评估:pcntl_wifexited()、pcntl_wifstopped()、pcntl_wifsignaled()、pcntl_wexitstatus()、pcntl_wtermsig() 和 pcntl_wstopsig()。
flags
flags
的值是以下两个全局常量OR
在一起的值(零或多个)
WNOHANG |
如果没有子进程退出,则立即返回。 |
WUNTRACED |
返回已停止且其状态尚未报告的子进程。 |
pcntl_waitpid() 返回已退出的子进程的进程ID,错误时返回-1,如果使用了WNOHANG
且没有可用的子进程则返回零。
请注意,如果您在编译php时使用配置选项 --enable-sigchild(启用PHP自己的SIGCHLD处理程序)(在我的情况下,使用linux 2.6.18-53.1.13.el5.centos.plus和php 5.2.5),则php脚本中的pcntl_waitpid和pcntl_wait将永远不会返回子进程pid,因为内置的句柄会先获取它。
<?php
$childs = array();
// 派生一些进程。
for($i = 0; $i < 10; $i++) {
$pid = pcntl_fork();
if($pid == -1)
die('无法派生');
if ($pid) {
echo "父进程 \n";
$childs[] = $pid;
} else {
// 休眠 $i+1 (s)。子进程可以获取此参数 ($i)。
sleep($i+1);
// 子进程需要结束循环。
exit();
}
}
while(count($childs) > 0) {
foreach($childs as $key => $pid) {
$res = pcntl_waitpid($pid, $status, WNOHANG);
// 如果进程已退出
if($res == -1 || $res > 0)
unset($childs[$key]);
}
sleep(1);
}
?>
<?php
declare(ticks = 1);
function zp_handler($signal) {
$id = pcntl_waitpid(-1, $status, WNOHANG);
if (pcntl_wifexited($status))
{
printf("已移除子进程 ID: %d \n",$id);
printf("子进程状态: %d \n",pcntl_wexitstatus($status));
}
}
//pcntl_signal_dispatch();
pcntl_signal(SIGCHLD, "zp_handler");
//pcntl_signal_dispatch();
//
$pid = pcntl_fork();
if ($pid == 0)
{
print "#1 你好,我是子进程\n";
sleep(3);
return 10;
}
else
{
print "#1父进程 ID:".$pid.PHP_EOL;
$pid = pcntl_fork();
if ($pid == 0)
{ print "#2 你好,我是子进程\n";
sleep(10);
exit(20);
}
else
{
print "#2父进程 ID:".$pid.PHP_EOL;
for ($i=0; $i <10 ; $i++) {
print "等待…\n";
sleep(10);
}
}
}
?>