【问题标题】:Reading data from STDOUT of C application using PHP使用 PHP 从 C 应用程序的 STDOUT 读取数据
【发布时间】:2014-06-18 17:24:53
【问题描述】:

我想使用 PHP 中的 Web 界面分别读取和写入 C 应用程序的 STDOUT 和 STDIN。为此,我有一个测试 c 应用程序“hello.c”,它在特定睡眠后输出一个字符串,使用 PHP 我执行该 C 应用程序。我在 PHP 中使用流选择函数并检测该 C 应用程序的标准输出何时发生变化。我阅读了应用程序输出,但在 PHP 上,即使 C 应用程序输出已完成,我也会在 read discriptor 上更改状态。我的 c 应用程序、PHP 和浏览器输出代码如下所示;

hello.c

#include<stdio.h>

void main(void)
{
 int i = 0;

 for(i = 0; i < 5; i++)
    {
            printf("hello world\n");
            sleep(1);
    }

}

PHP

<?php
execute_prog('/var/www/html/test/./hello3');

function execute_prog($exe)
{

    set_time_limit(1800);


        $exe_command = escapeshellcmd($exe);

    $descriptorspec = array(

            0 => array("pipe", "r"),  // stdin -> for execution

            1 => array("pipe", "w"),  // stdout -> for execution

            2 => array("pipe", "w") // stderr 

        );

    $process = proc_open($exe_command, $descriptorspec, $pipes);//creating child process


     if (is_resource($process))
      {
            while(1)
        {
            $write  = NULL; 
            $read   = array($pipes[1]);
            $err    = NULL;
            $except = NULL;

            if (false === ($num_changed_streams = stream_select($read, $write, $except, 0)))
            {
                /* Error handling */
                                echo "Errors\n";
            } 
            else if ($num_changed_streams > 0)
            {
                     /* At least on one of the streams something interesting happened */

                        //echo "Data on ".$num_changed_streams." descriptor\n";

                 if($read)
                 {
                     echo "Data on child process STDOUT\n";

                     $s = fgets($pipes[1]);
                     print $s."</br>";


                     flush();
                 }
                 else if($write)
                 {
                     echo "Data on child process STDIN\n";

                 }
                 else if($err)
                 {
                     echo "Data on child process STDERR\n";

                 }

                $num_changed_streams = 0;
            }


        }

        fclose($pipes[0]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        echo "exitcode: ".proc_close($process)."\n";
    }   


return $ret;
}

?>

PS 命令的结果

 ps -eaf | grep hello
 apache   24157 22641  0 10:01 ?        00:00:00 [hello3] <defunct>

浏览器输出

Data on child process STDOUT hello world

Data on child process STDOUT hello world

Data on child process STDOUT hello world

Data on child process STDOUT hello world

Data on child process STDOUT hello world

Data on child process STDOUT

Data on child process STDOUT

Data on child process STDOUT

知道为什么我不断收到“关于子进程 STDOUT 的数据”吗?在持续显示此文本时,“ps”结果仍如上所示。

请指导。

编辑 我添加了一个调整,当 fgets 的结果为空时,我打破了 while 循环

 $s = fgets($pipes[1]);

 if(empty($s))
 {
    echo "Empty";
    break;  
 }

现在不显示连续的“关于子进程 STDOUT 的数据”。正如我所说的那样,即使 C 应用程序停止发送数据,我仍然不知道为什么读取描述符会变为真。有人请

【问题讨论】:

    标签: php c linux stdout multitasking


    【解决方案1】:

    你错过了 hello 程序停止输出并终止的那一刻(并且它的进程变得“失效”)。一般fgets( $some_file )如果有输出返回一个字符串,如果$some_file已经结束返回false。因此,如果您添加此检查:

    $s = fgets($pipes[1]);
    if( $s === false ) {
        // Hello program has finished.
        echo 'Finished', PHP_EOL;
        // Close all descriptors and return...
    }
    

    您应该成功终止。

    【讨论】:

    • 您的解决方案类似于上面给出的调整,我正在使用您的代码,因此接受它作为答案:) 谢谢
    • 对不起,我没有对您的编辑给予足够的重视,在这种情况下它确实给出了相同的结果。我希望我至少设法解释了它为什么起作用:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多