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

标签 php c linux stdout multitasking

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

你好.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 应用程序停止发送数据,读取描述符也会变为真。任何人请

最佳答案

你错过了 hello 程序停止输出并终止(并且它的进程变成“defunct”)的那一刻。通常,如果有输出,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...
}

你应该成功终止。

关于php - 使用 PHP 从 C 应用程序的 STDOUT 读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23421154/

相关文章:

php - 如何即时更改 Yii 错误处理程序?

php - PDO 中字符串附加问号

c - 按位运算并检查整数的第 n 位

linux - rsync - 将文件复制到另一台服务器

php - FastCGI 进程超过配置的事件超时

php - Tinymce - 插入html代码

c - 如何改进我的代码以从文本表填充数组?

c - 如何让 gcc 打印出可执行文件所需的共享库的确切路径

linux - 使用 awk/sed 在制表符分隔文件中间添加重复内容

linux - Eyaml 和 Puppet