【问题标题】:php forking child process to execute infinte loopsphp forking子进程执行无限循环
【发布时间】:2014-04-28 18:36:39
【问题描述】:

我对 php 比较陌生,但我可以用其他语言(js、java、c/c++)编程。我有一个问题,我似乎无法解决,所以我希望有人可以在这里帮助我:)

我创建了一个 server_class.php 文件来管理多个客户端之间的连接。客户端通过网络连接到 php 服务器。当我启动 server_class.php 时,它会执行两个应用程序(它们处于无限循环中)并将数据打印到终端。当客户端连接到 php 服务器时,我希望服务器开始将每个应用程序的输出发送到每个客户端,以便客户端可以看到每个应用程序的当前输出。我已经部分实现了这一点。但是,它只发送一个应用程序的输出,而不发送另一个应用程序的输出。

服务端与客户端连接时执行如下函数:

private function startProc($client) {
    $this->output("Start a client process");
    $pid = pcntl_fork();
    if($pid == -1) {
        $this->output("fork terminated!");
    }
    elseif($pid) { // process
        $client->setPid($pid);
    }
    else {
        $this->output("Starting app1 data pipe...");
        exit($this->launchAppOneProc($client));

        $this->output("Starting app2 data pipe...");
        exit($this->launchAppTwoProc($client));
    }
}

好的,一旦客户端和服务器之间的连接完成,这个函数就会被执行。如您所见,我创建了一个新进程,然后执行两个方法:launchAppOneProc 和launchAppTwoProc。这两个函数包含以下代码:

private function launchAppOneProc($client) {
    while (@ ob_end_flush()); // end all output buffers if any

    while (!feof($this->appone_proc))
    {   
        $appone_text = fread($this->appone_proc, 4096);
        $this->send($client, $appone_text);
        flush();
    }

    $this->output("AppOne has stopped running!");
}

上面的函数与launchAppTwoProc()的函数相同。函数 $this->output 将指定的文本打印到 server_class.php 的终端中

所以问题是它只执行了launchAppOneProc()函数,没有执行下一个函数launchAppTwoProc()。

关于如何执行这两个功能的任何想法?

谢谢 大卫

【问题讨论】:

  • 您在$this->launchAppOneProc(...)$this->launchAppTwoProc(...) 之间有一个exit 语句。
  • 感谢您的回复,但即使删除了包含两个函数调用的退出函数,问题仍然存在。
  • 我不清楚你的各种程序是如何设置的,但是可能会发生一点混乱:分叉后,父进程和子进程都会有相似的数据(变量等),但更改其中一个数据不会更改另一个中的相应数据。

标签: php process fork


【解决方案1】:

好的,我找到了解决问题的方法。为了消除一些混乱,我有两个应用程序在后台运行并写入缓冲区。当客户端连接到服务器时,它们连接到两个缓冲区并开始接收数据。所以我所做的是为每个渠道创建一个新流程。当客户端连接到服务器时,会创建两个进程并分配给客户端。每个进程都连接到一个缓冲区并开始向客户端发送数据。

private function startProc($client) {
    $this->output("Start a client process");

    for ($i = 0; $i < 2; ++$i) {
        // Create new process.
        $pid = pcntl_fork();

        switch ($pid) {
            case -1: // Failed to create new process.
                $this->output("Failed to create new process!");
                break;

            case 0: // Child process created, execute code...
                switch ($i) {
                    case 0:
                        $this->output("Connect to AppOne data pipe...");
                        $this->launchAppOneProc($client);
                        break;

                    case 1:
                        $this->output("Connect to AppTwo data pipe...");
                        $this->launchAppTwoProc($client);
                        break;
                }

            default: // Back to parent.
                switch ($i) {
                    case 0:
                        $client->setAppOnePid($pid);
                        break;
                    case 1:
                        $client->setAppTwoPid($pid);
                        break;
                }
        }
    }
}

我知道我可以使用数组来存储进程 ID 等。但现在,这可行。一旦客户端断开连接,刚刚离开的客户端的每个进程都必须这样终止:

posix_kill($client->getAppOnePid(), SIGTERM);
posix_kill($client->getAppTwoPid(), SIGTERM);

我希望这是有道理的,并且可以帮助遇到同样问题的任何人。

【讨论】:

    猜你喜欢
    • 2012-11-16
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多