3

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

我的 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');效果很好,但如果我使用 php 脚本会挂起 fwrite($pipes[0], '');以保持程序运行......

编辑:我在没有成功的情况下调查了缓冲问题$process = proc_open('stdbuf -i0 /home/tristan/www/a.out', $descriptorspec, $pipes, $cwd, $env);......

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

谢谢你的帮助!

4

2 回答 2

2

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

  • stream_get_contents()将永远挂起,等待一个EOL永远不会出现的 C 代码在无限循环中运行。您必须使用stream_set_blocking()以防止stream_get_contents()阻塞

  • proc_close()除非进程终止,否则也会永远等待。由于无限循环,这永远不会发生。您必须使用显式终止它proc_terminate()(这根本没有多大意义)

我已经准备了一个代码如何不会挂起的示例,但我需要说,您的代码没有多大意义。我会将 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";
}
于 2013-07-04T12:20:52.440 回答
0

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

<?php

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

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

    $proc = popen('./a.out < /tmp/progIn > /tmp/progOut &', 'r');
}
?>
于 2013-09-10T15:14:48.153 回答