apache PHP:pcntl_fork() 到底有什么作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2038586/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 18:36:10  来源:igfitidea点击:

PHP: What does pcntl_fork() really do?

phpapachethread-safetyforkprocess-control

提问by GetFree

PHP's pcntl_fork function is supposed to fork a process just as the standard fork function in C.
But I was wondering if this function really forks the process or if it emulates that behavior in a different way.
If it really forks the process then it's clear which process that is: one of Apache's child processes.
That's OK as long as Apache is using the prefork MPM (i.e. one process per request).
But what does happen if Apache is using the worker MPM??
When the worker MPM is being used, every Apache child process contains many threads, each one handling a different HTTP request. So if you would fork the process under that situation I can't even think what would happend to all those threads and requests being served.
So if pcntl_fork() really forks the process then I think it's not a good idea to use this function if you set Apache to use the worker MPM.

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

What do the experts say? Am I reasoning well, or I'm just speaking nonsense?

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

回答by Pascal MARTIN

pcntl_forkprobably works as you think it would : it forks the current process, the same way the C function fork does :

pcntl_fork可能像您认为的那样工作:它分叉当前进程,与 C 函数分叉的方式相同:

The pcntl_fork()function creates a child process that differs from the parent process only in its PID and PPID.
Please see your system's fork(2)man page for specific details as to how fork works on your system.

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


But, quoting the Introduction of the Process Controlsection of the manual :


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

Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination.
Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.

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

So, you should not actually use that function from a PHP script executed via Apache : it should only be used when your PHP script is executed from the command-line.

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


And, before starting to use that function, don't forget that :


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

Note: This extension is not available on Windows platforms.

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

回答by Emil Vikstr?m

It's not a good idea to run PHP as a module on an Apache installation configured for worker MPM in the first place, because PHP is not threadsafe (I think that is stated somewhere in the PHP manual too).

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

It should fork the process, yes. The PHP manualeven states that you should read man fork(2)for further instructions, so it's probably just a wrapper around the C fork function.

它应该分叉这个过程,是的。在PHP手册甚至指出你应该阅读man fork(2)获取进一步的说明,所以它可能只是以C fork函数的包装。

Update: Here's the relevant page in the PHP manual for worker MPM: http://php.net/install.unix.apache2.php

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

Note: To build a multithreaded version of Apache, the target system must support threads. In this case, PHP should also be built with experimental Zend Thread Safety (ZTS). Under this configuration, not all extensions will be available. The recommended setup is to build Apache with the default prefork MPM-Module.

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

I also found this page with some further instructions: http://www.stevekallestad.com/blog/apache_worker_mpm_with_php.html

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

回答by Daniel Andres Acevedo

I'll try to be quick and concise,

我会尽量简洁明了,

Using "fork" through apache it is possible, you need to "install" then enable the functions in the php.ini, finally you need to add the extension in the apache directori (a symlink would have the job done as well) Ex:

通过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 

On the other hand, I've been using forking for a lot of projects and it is really great at optimizing most of them, however, there is a bug when abusing of it with apache, im basically forking the forked child and doing anykind of hardcore stuff and it works... pretty good, but under load it works for some time before start to creating zombie process, i can manage the zombie process using "pcntl_signal(SIGCHLD, SIG_IGN);" which basically will remove the process as soon as the child finish their task, this help a little bit, then is when apache goes crazy, and start threading itself and finally crashing your server, i cannot explain this behavior (yet, but i will) this weir/evil tree created by apache can only be seen from "ps" nor from server-status or apache logs, and i said evil tree because it basically creates hundred of process with children of children...

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

in nutshell:

简而言之:

Fork with apache will work? YES... absolutely

Fork 与 apache 会起作用吗?是的,一点没错

just dont abuse of it

只是不要滥用它

hope this will help some one

希望这会帮助某人

回答by bourneli

I have just tried to use pcntl_fork via apache, the strange situation is that after fork a child process, the parent give the standard output(browser) to its child. So, you can image, the browser cann't receive the output from the parent process.

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