这只是一个测试脚本。在生成一个简单的lib之前,我正在测试基本的子叉功能,以便生成多个进程,在php中并行处理数据批处理。在继续之前,我还需要测试些什么来理解吗?据我所知,所有资源都是在分叉期间复制的,因此初始化/打开叉子之后所需的任何资源。
<?php
$childcount = 10;
for($i = 1; $i <= $childcount; $i ++)
{
$pid = pcntl_fork();
if ($pid == -1) {
echo "failed to fork on loop $i of forking\n";
} else if ($pid) {
// we are the parent
$pidArray[$pid] = $pid;
// and we want to wait on all children at the end of the loop
} else {
// we are the child
echo "Child is outputting it's count and dying. Count: $i \n ";
doMessage($i);
die;
}
}
echo "sleeping to see if child finished events queue\n";
sleep(10);
print_r($pidArray);
for($j = 1; $j <= $childcount; $j++)
{
echo "parent is waiting on child\n";
$pid = pcntl_wait($status); //Wait for random child to finish
$pidArray[$pid] = "terminated";
echo "parent found $j of the finished children\n";
}
print_r($pidArray);
function doMessage($location)
{
sleep (rand(4,20));
echo "outputting concurrently : $location \n";
}输出如下:
me@myhost:~/$]: php test.php
sleeping to see if child finished events queue
Child is outputting it's count and dying. Count: 3
Child is outputting it's count and dying. Count: 4
Child is outputting it's count and dying. Count: 5
Child is outputting it's count and dying. Count: 6
Child is outputting it's count and dying. Count: 8
Child is outputting it's count and dying. Count: 9
Child is outputting it's count and dying. Count: 10
Child is outputting it's count and dying. Count: 7
Child is outputting it's count and dying. Count: 2
Child is outputting it's count and dying. Count: 1
outputting concurrently : 9
outputting concurrently : 1
outputting concurrently : 6
Array
(
[22700] => 22700
[22701] => 22701
[22702] => 22702
[22703] => 22703
[22704] => 22704
[22705] => 22705
[22706] => 22706
[22707] => 22707
[22708] => 22708
[22709] => 22709
)
parent is waiting on child
parent found 1 of the finished children
parent is waiting on child
parent found 2 of the finished children
parent is waiting on child
parent found 3 of the finished children
parent is waiting on child
outputting concurrently : 5
parent found 4 of the finished children
parent is waiting on child
outputting concurrently : 2
parent found 5 of the finished children
parent is waiting on child
outputting concurrently : 3
parent found 6 of the finished children
parent is waiting on child
outputting concurrently : 8
parent found 7 of the finished children
parent is waiting on child
outputting concurrently : 7
parent found 8 of the finished children
parent is waiting on child
outputting concurrently : 4
outputting concurrently : 10
parent found 9 of the finished children
parent is waiting on child
parent found 10 of the finished children
Array
(
[22700] => terminated
[22701] => terminated
[22702] => terminated
[22703] => terminated
[22704] => terminated
[22705] => terminated
[22706] => terminated
[22707] => terminated
[22708] => terminated
[22709] => terminated
)我还确认了额外的pctl_wait将立即返回pid值为-1。
发布于 2011-06-07 20:16:58
您的示例没有触及您可以使用pcntl_fork进行封装的问题。
请记住,fork()会复制程序,这意味着所有描述符都会被复制。不幸的是,对于PHP程序来说,这是一个相当糟糕的情况,因为大多数描述符都是由PHP或PHP扩展在内部处理的。
解决这个问题的简单而且可能是“适当”的方法是手前分叉,实际上不需要在程序之间的许多不同点进行分叉,您可以简单地分叉,然后委托工作。使用主/工层次结构。
例如,如果您需要有许多使用MySQL连接的进程,那么在建立连接之前就需要分叉,这样每个子节点都有它自己和它单独管理的mysql连接。
另一件需要注意的事情是,当一个子进程死亡时。死亡应该由父母来处理。如果不是,那么子进程就会变成僵尸:它不消耗资源,但它仍然是一个带有PID的进程。这是不可取的,因为大部分(全部?)操作系统对它能够处理的进程有一个上限。
当一个孩子死后,一个信号被发送给父(SIGCHLD)。然后,父级可以处理子节点的死亡,以进行内部处理。正确的方法是使用pcntl_waitpid()来解除孩子的僵尸。您可以使用该函数来等待孩子死亡,或者检测一个孩子已经死了。当您想要对无数个孩子执行此操作时,请使用pcntl_wait()。查看PHP手册的相关部分以获得更多选项(包括让函数知道不挂起正常操作)。
然而,使用SIGCHLD并不总是万无一失的。当您快速创建许多短命子程序时,结合pcntl_waitpid()处理SIGCHLD可能不会处理所有僵尸进程。
希望这能帮上忙,php.net上的文档没问题,但在我看来,这些功能很容易被误用,所以在主题和潜在的陷阱方面可能会更深入。
下面是一个简单的示例(从php.net注释中提取),它显示了将资源分配给父线程的错误:
<?php
mysql_connect(/* enter a working server here maybe? */);
$f=pcntl_fork();
while(true){
sleep(rand(0,10)/100);
$r=mysql_query("select $f;");
if(!$r)die($f.": ".mysql_error()."\n");
list($x)=mysql_fetch_array($r);
echo ($f)?".":"-";
if($x!=$f) echo ($f.": fail: $x!=$f\n ");
}
?>在cli上运行这个将超过不同的结果:
希望在扩展示例以获取数据和/或使用重新源时,这会有所帮助。
祝你快乐!
https://stackoverflow.com/questions/6270930
复制相似问题