PHP:pcntl_fork()真正做什么?

时间:2010-01-10 20:59:30

标签: php apache thread-safety fork process-control

PHP的pcntl_fork函数应该像C中的标准fork函数一样分叉一个进程 但我想知道这个功能是否真的要求这个过程,或者它是否以不同的方式模仿这种行为 如果它真的要求进程,那么很清楚哪个进程是:Apache的子进程之一 只要Apache使用prefork MPM(即每个请求一个进程),就可以了 但是如果Apache使用worker MPM会发生什么呢? 当使用worker MPM时,每个Apache子进程都包含许多线程,每个线程处理不同的HTTP请求。因此,如果您在这种情况下分叉流程,我甚至无法想到所有这些线程和请求将会发生什么 因此,如果pcntl_fork()真的要求进程,那么我认为如果你将Apache设置为使用worker MPM,那么使用这个函数并不是一个好主意。

专家们说什么?我推理得好,或者我只是胡说八道?

4 个答案:

答案 0 :(得分:21)

pcntl_fork可能会像您认为的那样工作:它会分叉当前进程,就像C函数fork一样:

  

pcntl_fork()函数创建一个   与...不同的子过程   父进程只在其PID和   PPID。
请查看您的系统   特定的fork(2)手册页   有关fork如何工作的详细信息   系统


但是,引用手册的Introduction of the Process Control部分:

  

PHP中的过程控制支持   实现Unix风格的流程   创作,程序执行,信号   处理和流程终止。   
过程控制不应该   在Web服务器中启用   环境和意外结果可能   发生任何过程控制   功能在Web服务器中使用   环境。

因此,您不应该在通过Apache执行的PHP脚本中实际使用该函数:它只应在从命令行执行PHP脚本时使用。


并且,在开始使用该功能之前,请不要忘记:

  

注意:此扩展程序不可用   在Windows平台上。

答案 1 :(得分:3)

首先在为工作者MPM配置的Apache安装上运行PHP作为模块并不是一个好主意,因为PHP不是线程安全的(我认为这也在PHP手册的某处说明)。

应该分叉这个过程,是的。 PHP manual甚至声明您应该阅读man fork(2)以获取进一步的说明,因此它可能只是C fork函数的包装器。

更新:这是工作者MPM的PHP手册中的相关页面: http://php.net/install.unix.apache2.php

  

注意:要构建Apache的多线程版本,目标系统必须支持线程。在这种情况下,PHP也应该使用实验性的Zend Thread Safety(ZTS)构建。在此配置下,并非所有扩展都可用。推荐的设置是使用默认的prefork MPM-Module构建Apache。

我还在这个页面上找到了一些进一步的说明: http://www.stevekallestad.com/blog/apache_worker_mpm_with_php.html

答案 2 :(得分:3)

我会尽量快速简洁,

使用" fork"通过apache它是可能的,你需要"安装"然后启用php.ini中的函数,最后你需要在apache directori中添加扩展名(符号链接也可以完成工作) 例如:

echo "extension=pcntl.so" > /etc/php5/conf.d/pcntl.ini
ln -s /etc/php5/apache2/conf.d/pcntl.ini /etc/php5/mods-available/pcntl.ini 

另一方面,我一直在使用forking进行很多项目,并且它非常适合优化大多数项目,但是,当用apache滥用它时有一个bug,我基本上是在分叉孩子和做任何铁杆的东西,它的工作......非常好,但在加载它工作一段时间后才开始创建僵尸进程,我可以使用" pcntl_signal(SIGCHLD,SIG_IGN)管理僵尸进程;& #34;这基本上会在孩子完成任务后立即删除这个过程,这有点帮助,然后就是当apache发疯,并开始线程化并最终崩溃你的服务器时,我无法解释这种行为(但是,我会)这个由apache创建的堰/邪恶树只能从" ps"也不是从服务器状态或apache日志,我说邪恶的树,因为它基本上创造了一百个孩子的孩子的过程......

简而言之:

用pache fork会有用吗?是的......绝对

不要滥用它

希望这会对某人有所帮助

答案 3 :(得分:0)

我刚刚尝试通过apache使用pcntl_fork,奇怪的情况是,在fork子进程之后,父进程将标准输出(浏览器)提供给它的子进程。因此,您可以进行映像,浏览器无法从父进程接收输出。