使用PHP从C应用程序的STDOUT读取数据

时间:2014-05-02 05:09:06

标签: php c linux stdout multitasking

我想阅读&写STDOUT& STDIN分别是使用PHP中的Web界面的C应用程序。为此我有一个测试c应用程序“hello.c”,在某些睡眠后输出一个字符串,使用PHP我执行该C应用程序。我在PHP中使用流选择功能,并检测该C应用程序的stdout何时发生更改。我读取了应用程序输出,但在PHP上,即使C应用程序输出完成,我也会在读取discriptor上获得状态更改。我的c app,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应用程序停止发送数据,读取描述符也变为真实。有人请

1 个答案:

答案 0 :(得分:1)

你错过了hello程序停止输出并终止的那一刻(并且它的进程变为&#34;废弃&#34;)。通常,如果有输出,fgets( $some_file )会返回一个字符串,如果false已到达结尾,则返回$some_file。因此,如果您添加此检查:

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

你应该成功终止。