我想使用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);
但没有成功......
有没有人知道如何监控值并以交互方式向程序发送命令?
谢谢你的帮助!
答案 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');
}
?>