13

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

专家怎么说?我推理得很好,还是我只是在胡说八道?

4

4 回答 4

22

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

pcntl_fork()函数创建一个子进程,该子进程与父进程的区别仅在于它的 PID 和 PPID。有关 fork 如何在您的系统上工作的具体细节,
请参阅您系统的 手册页。fork(2)


但是,引用手册的过程控制部分的介绍:

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

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


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

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

于 2010-01-10T21:10:06.700 回答
3

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

它应该分叉这个过程,是的。PHP 手册甚至指出您应该阅读以man fork(2)获取更多说明,因此它可能只是 C fork 函数的包装。

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

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

我还发现这个页面有一些进一步的说明: http: //www.stevekallestad.com/blog/apache_worker_mpm_with_php.html

于 2010-01-10T21:04:20.533 回答
3

我会尽量快速简洁,

通过 apache 使用“fork”是可能的,您需要“安装”然后启用 php.ini 中的功能,最后您需要在 apache 目录中添加扩展名(符号链接也可以完成工作)例如:

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 

另一方面,我一直在为很多项目使用分叉,它在优化大多数项目方面非常出色,但是,在使用 apache 滥用它时存在一个错误,我基本上是分叉了分叉的孩子并做任何事情硬核的东西,它工作......非常好,但在负载下它在开始创建僵尸进程之前工作了一段时间,我可以使用“pcntl_signal(SIGCHLD,SIG_IGN);”管理僵尸进程 这基本上会在孩子完成任务后立即删除该过程,这会有所帮助,然后是当 apache 发疯,开始线程化并最终导致服务器崩溃时,我无法解释这种行为(但我会)这个由 apache 创建的 weir/evil 树只能从“ps”中看到,也不能从服务器状态或 apache 日志中看到,

简而言之:

用 apache 分叉可以吗?是的,一点没错

只是不要滥用它

希望这会帮助一些人

于 2016-01-11T15:38:07.390 回答
0

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

于 2012-07-06T08:53:19.337 回答