代码之家  ›  专栏  ›  技术社区  ›  d-_-b

先是pcntl_fork,然后是pcntl_exec或pcntl_exec,然后是pcntl_fork

  •  2
  • d-_-b  · 技术社区  · 15 年前

    说明: 我正在创建的应用程序的一部分需要检查数以千计的记录并在 及时

    我想我可以使用pcntl_exec('php/path/script.php');然后使用pcntl_fork,这样调用过程就不会被延迟。

    我的问题是:

    笔记: 也许我是在想象这个问题,因为我认为调用php进程将等待pcntl_exec返回。但医生并不是这么说的:

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

    fahadsadah的评论说:

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

    如果是这样的话,那我就得用叉子了。

    <?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]);
    

    如果取消注释exec并注释pcntl_exec,您将看到pcntl_exec替换了进程。我想这会节省一些资源。

    3 回复  |  直到 15 年前
        1
  •  1
  •   symcbean    15 年前

    这真的很混乱-你试图应用非常复杂的技术-但你完全用错误的方式应用它们。

    fork创建当前进程的新运行副本。Exec启动一个新进程。你不能同时使用它们来启动一个进程。

    应尽可能避免批量处理。数据通常以有限的速率到达(尽管速率可能是随机的)-通常避免批处理的正确方法是同步或通过排队处理请求。当批量处理不可避免时,并行化和/或流水线处理 提高吞吐量。虽然有许多复杂的方法可以实现这一点(例如map reduce),但是仅仅对数据进行分片通常就足够了。虽然你的基本想法相当于分成几个部分,但这:

    1) 会比处理小批量产品效率低

    2) 很难限制系统的资源消耗(如果生成500个进程,而DBMS只支持200个并发连接呢?)

    假设您不能同时处理处理,并且使用多个订阅者运行一个队列是不实际的,我建议将数据分成(数量有限的)较小的批并生成处理这些数据的进程。请注意,popen()、proc_open()和pcntl_fork()在派生进程的执行期间不会阻塞。(提示-使用 modulus operator )

    如果您想从HTTP请求启动处理(或者有另一个理由在单独的会话组中运行它们),那么就使用google for'PHP long running processes setid'。

        2
  •  0
  •   user207421    15 年前

    这没道理。一旦exec()运行不同的代码 不能 fork()之后。

        3
  •  0
  •   Joseph Bloe    15 年前

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

    想象一下当使用维护自己文件描述符的mysql扩展时会带来的灾难;-)