使用php交互式控制程序

时间:2013-07-04 10:49:38

标签: php html c controls

我想使用php在远程计算机上运行C程序。最终目标是使用手机或任何其他计算机上的Web浏览器控制程序。

我的C程序在几十分钟内从不同传感器获取数据。它从linux中的命令行运行,我可以通过按计算机键盘上的“q”键将其关闭。主线程是这样的:

int main(){

    printf("Program is running... Press 'q' <enter> to quit\n");

    fflush(stdout);

    //create one thread per sensor

        while (getchar() != 'q'){
        }

    //ask the threads to terminate  

    return(0);
}

每个线程执行一些printf以给出每个传感器的状态。我想在手机上监控这些值,并有一个按钮来终止远程程序。

我可以使用system(),open()或proc_open()成功监控这些值。它的问题是主程序中的getchar。它挂起了PHP脚本......

<?php

    if(isset($_POST['start'])){

        $descriptorspec = array(
           0 => array("pipe", "r"),  // // stdin est un pipe où le processus va lire
           1 => array("pipe", "w"),  // stdout est un pipe où le processus va écrire
           2 => array("file", "/tmp/error-output.txt", "a") // stderr est un fichier
        );

        $cwd = '/tmp';
        $env = array();

        $process = proc_open('/home/tristan/www/a.out', $descriptorspec, $pipes, $cwd, $env);

        if (is_resource($process)) {

            fwrite($pipes[0], 'q');

            fclose($pipes[0]);

            echo stream_get_contents($pipes[1]);
            fclose($pipes[1]);

            $return_value = proc_close($process);

            echo "La commande a retourné $return_value\n";
        }
    }
?>

使用fwrite($pipes[0], 'q');效果很好,但如果我使用fwrite($pipes[0], '');以保持程序运行,则php脚本会挂起...

编辑:我忽略缓冲问题$process = proc_open('stdbuf -i0 /home/tristan/www/a.out', $descriptorspec, $pipes, $cwd, $env);但没有成功......

有没有人知道如何监控值并以交互方式向程序发送命令?

谢谢你的帮助!

2 个答案:

答案 0 :(得分:2)

上面的PHP代码有两个问题让你的程序挂起:

  • stream_get_contents()将永远挂起,等待EOL从未出现,因为C代码在无限循环中运行。您必须使用stream_set_blocking()来阻止stream_get_contents()阻止

  • 除非进程已终止,否则
  • proc_close()也会永远等待。由于无限循环,这种情况永远不会发生。你必须使用proc_terminate()明确地终止它(这对imo来说没什么意义)

我已经准备了一个示例,代码不会挂起,但我需要说,你的代码没有多大意义。我会将C程序编写为侦听UNIX域套接字的UNIX守护程序。然后,您可以为命令设计简单的基于文本的通信协议。然后用PHP连接到套接字。但也许我错了,因为我不详细了解您的应用场景。

然而,这是您的固定代码:

$descriptorspec = array(
   0 => array("pipe", "r"),  // // stdin est un pipe où le processus va lire
   1 => array("pipe", "w"),  // stdout est un pipe où le processus va écrire
   2 => array("file", "/tmp/error-output.txt", "a") // stderr est un fichier
);

$cwd = '/tmp';
$env = array();

$process = proc_open(__DIR__ . '/a.out', $descriptorspec, $pipes, $cwd, $env);

if (is_resource($process)) {

    fwrite($pipes[0], ' ');
    fclose($pipes[0]);

    // set stream to unblocking mode
    stream_set_blocking($pipes[1], 0);
    // now the following line will not wait forever
    // for an EOF
    echo stream_get_contents($pipes[1]);

    fclose($pipes[1]);

    // proc_close will wait until the process has finished - forever in this case
    // if you want to terminate the process. You'll have to terminate it explicitely
    proc_terminate($process);
    $return_value = proc_close($process);

    // if you want  to have a meaningful return value
    // you'll have to implement a handler for SIGTERM 
    // in your C program
    echo "La commande a retourné $return_value\n";
}

答案 1 :(得分:0)

我终于得到了我想在system()函数中使用管道的东西:

<?php

if(isset($_POST['start'])){

    system('> /tmp/progOut');
    system('mkfifo /tmp/progIn');

    $proc = popen('./a.out < /tmp/progIn > /tmp/progOut &', 'r');
}
?>