首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >pcntl_fork然后是pcntl_exec或pcntl_exec然后是pcntl_fork

pcntl_fork然后是pcntl_exec或pcntl_exec然后是pcntl_fork
EN

Stack Overflow用户
提问于 2010-10-22 05:08:44
回答 3查看 4.6K关注 0票数 2

解释:我正在创建的应用程序的一部分需要检查数千条记录,并及时对它们进行操作。因此,对于每一个记录,我都想启动一个新的过程。但是,我需要一个DB连接来对记录进行更多的检查。据我所知,子节点继承DB连接。因此,后续的分叉存在DB错误。

我想我可以pcntl_exec('php /path/script.php‘),然后是pcntl_fork,这样调用进程就不会被阻塞。

或者我可以在子进程中使用pcntl_fork,然后是pcntl_exec。或者我应该使用exec()而不是pcntl_exec()。

我的问题是:这两种订单都有什么缺点或优点吗?

注释:可能是我想象的问题,因为我认为调用pcntl_exec进程将等待pcntl_exec返回。但这不是医生们所说的:

错误时返回FALSE,而成功时不返回。

函数如何有时返回值,而不返回其他时间的值?听起来像是写得不好的文档。

法哈德萨达的评论说:

一旦执行的进程结束,控件将返回到the服务器进程。

如果是这样的话,我就得分叉了。

编辑:困惑者的代码--包括我;)

代码语言:javascript
复制
<?php

class Process
{

    public function __construct($arg = false)
    {
        if ($arg == "child")
        {
            $this->act();
        }
        else
        {
            $this->run();
        }
    }

    public function run()
    {
        echo "parent before fork:", getmypid(), PHP_EOL;
        $pid = @ pcntl_fork();
        echo $pid, PHP_EOL;

        if ($pid == -1)
        {
            throw new Exception(self::COULD_NOT_FORK);
        }
        if ($pid)
        {
        // parent
            echo "parent after fork:", getmypid(), PHP_EOL;
        }
        elseif ($pid == 0)
        {
        // child
            echo "child after fork:", getmypid(), PHP_EOL;
            //echo exec('php Process.php child');
            echo pcntl_exec('/usr/bin/php', array('Process.php', 'child'));
        }
        return 0;
    }

    private function act()
    {
        sleep(1);
        echo "forked child new process:", getmypid(), PHP_EOL;
        return 0;
    }
}

$proc = new Process($argv[1]);

如果取消对执行部分的注释并对pcntl_exec进行注释,您将看到pcntl_exec替换了该进程。我猜这能节省一些资源。

EN

回答 3

Stack Overflow用户

发布于 2010-10-22 08:56:44

这确实让人困惑--你试图应用非常复杂的技术--但你却完全错误地应用了它们。

叉创建当前进程正在运行的新副本。执行开始一个新的过程。您不会同时使用它们来启动单个进程。

但是,在我解释如何正确使用fork和exec之前,我应该指出,它们不是解决这个问题的正确工具。

应尽可能避免批处理。数据通常以有限的速率到达(尽管速率可能是随机的)--通常避免批处理的正确方法是同步或通过排队处理请求。当批处理不可避免时,并行处理和/或流水线处理通常会提高吞吐量。虽然有许多复杂的方法来实现这一点(例如,map-还原),但简单地对数据进行切分通常是足够的。虽然您的基本想法相当于分片,但如下所示:

1)与处理小批量相比,效率较低

2)限制系统的资源消耗非常困难(如果您生成500个进程,而DBMS只支持200个并发连接,怎么办?)

假设您不能同步处理处理,并且与多个订阅者合并队列是不实际的,我建议只将数据分割成(有限数量)较小的批和产卵进程来处理。注意,popen()、proc_open()和pcntl_fork()不会在生成的进程执行期间阻塞。(提示-使用模算子)

如果您想从HTTP请求启动处理(或者在单独的会话组中运行它们的另一个原因),那么有一个google长期运行的进程setsid)。

票数 2
EN

Stack Overflow用户

发布于 2010-10-22 05:10:25

这没道理。一旦您运行了exec(),您就会运行不同的代码,因此以后您就不能分叉()了。不会在成功中回归。

票数 1
EN

Stack Overflow用户

发布于 2011-08-05 16:02:28

现在已经定义了叉和exec,fork不会做您想做的事情。它将将所有当前脚本环境复制到新空间,包括文件描述符指针。是的,这是正确的--孩子和父母共享相同的文件描述符。

想象一下当使用mysql扩展名维护自己的文件描述符时所造成的破坏;)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3994050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档