PHP中的pcntl_fork如何工作?

28

我对PHP中的pcntl_fork感到困惑。

我认为它实现了多线程,但它是如何工作的?并且在脚本中如何使用它呢?


请查看 http://stackoverflow.com/q/19546588/632951 - Pacerier
1个回答

61
PCNTL无法创建线程,它只能“fork”当前的PHP进程。这是什么意思?当您调用pcntl_fork()时,当前进程会被分成两个进程。父进程的整个命名空间都会被复制到子进程中,并且两个进程将并行执行,唯一的区别是:pcntl_fork()在父进程中返回子进程的PID,在子进程中返回0
一些提示:
  • 默认情况下它是禁用的。如果您设法启用它,请仅在CLI中使用。绝不要在Web服务器上使用!它将表现出不确定的方式。它也可能导致整个机器崩溃。请务必禁用它并继续阅读。
  • 进程之间的通信是可能的,但非常糟糕(通过共享内存中的序列化对象)。
  • 文件描述符(和数据库连接)是共享的,这经常会引起问题。 您必须在分叉后重新连接您的数据库,否则当它们中的第一个关闭连接时,所有分叉的进程都会收到来自MySQL server has gone away的错误。
  • 父进程必须等待子进程完成,否则它将留下僵尸进程消耗系统资源。

这里是一个来自文档的示例from documentation

<?php

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}

请记住,PHP只是一种脚本语言。它不适用于并行计算。根据您的需求,您可以通过同时运行CRON、消息队列或使用低级语言编写程序来更好地完成工作。
复制的PHP程序很难阅读、理解和调试。维护该程序将是一场噩梦。
不要犯错误,避免分叉。你不需要它。你真正需要的是异步任务运行器。好消息是,有RabbitMQ美好的教程 ;-) 你还可以尝试有前途的RabbitMQ库Bunny PS:与复制相比,使用消息队列还有一个好处。您可以使用多个服务器处理队列,并随着流量增长进行水平缩放。
编辑2019-03-07

我已经使用过异步并发框架amphp很多次,现在我要在这里提到它。如果你确实需要在单个请求中运行异步非阻塞任务,我认为amphp是目前最好的解决方案。它使用php生成器的概念($value = yield $promise)来执行人类可读的代码,而不会像reactphp一样陷入promise地狱。

https://amphp.org/


谢谢,你的回答帮了我 :) - Mehdi Maghrouni
你会推荐使用分叉创建守护进程吗? - Raheel
1
ReactPHP在没有安装C库时使用分叉,因此确保有一种简单的方法来处理分叉。 - Máxima Alekz
我在一个项目中工作,其中出现了分叉。我不开发分叉功能,因为它已经编写并正常工作。无论如何,该项目是一个大型的金融项目,它可以扩展并且易于维护。我并不是说分叉是最优解,但它确实可行。我猜想,如果你想在现实生活中的重要项目中应用这种技术,你需要相当丰富的经验。 - Jacek Dziurdzikowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接