【问题标题】:interactive control of a program using php使用php对程序进行交互控制
【发布时间】:2013-07-02 08:18:00
【问题描述】:

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

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

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

感谢您的帮助!

【问题讨论】:

  • 这个问题很有趣但很模糊。显示更多 C 代码并显示 PHP 代码
  • 是的。我尊重仍然使用 C 编程的人。它是一种强大的编程语言,我们可以使用它实际访问寄存器。希望你成功
  • 如果您将程序构建为作为守护程序运行并提供命令行工具来访问它,那么您可能会发现它更简单。查看 linux 如何提供服务:$ service {service-name} restart$ service {service-name} stop$ service {service-name} start (cyberciti.biz/tips/…)
  • 你应该按照汤姆所说的去做;您可以查看这里以了解如何创建守护进程 (netzmafia.de/skripten/unix/linux-daemon-howto.html)

标签: php html c controls


【解决方案1】:

上面的 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";
}

【讨论】:

    【解决方案2】:

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

    <?php
    
    if(isset($_POST['start'])){
    
        system('> /tmp/progOut');
        system('mkfifo /tmp/progIn');
    
        $proc = popen('./a.out < /tmp/progIn > /tmp/progOut &', 'r');
    }
    ?>
    

    【讨论】:

      猜你喜欢
      • 2015-01-17
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 2012-01-18
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多