PCNTL 函数
在线手册:中文 英文
PHP手册

pcntl_waitpid

(PHP 4 >= 4.1.0, PHP 5)

pcntl_waitpid等待或返回fork的子进程状态

说明

int pcntl_waitpid ( int $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 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: 等待或返回fork的子进程状态

用户评论:

brian dot ngure at gmail dot com (08-Jul-2009 04:03)

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

tunderzone at gmail dot com (25-Jun-2009 02:26)

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);
?>

saguto dot l7cc at gmail dot com (10-Apr-2008 05:09)

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.

Kevin (10-May-2006 11:40)

---
       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);
               }

admin at albert dot us dot com (06-Mar-2006 06:48)

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);