基本上我想用C(并且没有缓冲)和这个bash脚本一样:
#!/bin/sh
cat ./fifo_in | myprogram > ./fifo_out
换句话说,我想执行" myprogram"并将其stdin和stdout重定向到之前创建的两个管道。
另一个程序正在将数据输入fifo_in并读出fifo_out。
当然,只需从./fifo_in
读取,在父节点中缓冲并写入myprogram的stdin(对stdout和./fifo_out
反向)很容易,但我认为有可能是一种方法让#34; myprogram"直接从/向FIFO读取/写入而不在父进程中进行缓冲。
编辑:
欧根的回答似乎是正确的,但我无法让它发挥作用。我在C端使用这个功能,这对我来说是正确的:
pid_t execpipes(const char *wd, const char *command, const char *pipename)
{
char pipename_in[FALK_NAMESIZE];
char pipename_out[FALK_NAMESIZE];
strcpy(pipename_in, FALKPATH);
strcat(pipename_in, "/");
strcat(pipename_in, FALK_FIFO_PATH);
strcat(pipename_in, "/");
strncat(pipename_in, pipename, FALK_NAMESIZE-2);
strcpy(pipename_out, pipename_in);
strcat(pipename_out, "R");
pid_t pid;
pid = fork();
if (pid < 0)
{ //Error occured
perror("fork");
exit(1);
}
if (pid == 0)
{
chdir(wd);
d("execpipes: pipename_in=\"%s\"\n", pipename_in);
d(" pipename_out=\"%s\"\n", pipename_out);
freopen(pipename_in,"r",stdin);
freopen(pipename_out,"w",stdout);
d("execpipes: command=\"%s\"\n", command);
execl("/bin/sh", "sh", "-c", command, (char *)NULL); // using execv is probably faster
// Should never get here
perror("execl");
exit(1);
}
return pid;
}
我从PHP脚本中读取和编写管道(仅发布相关部分):
$pipe_in = fopen($fp.$pipename, "w");
$DEBUG .= "Write to pipe_in\n";
$ret = fwrite($pipe_in, $in);
$pipe_out = fopen($fp.$pipename.'R', "r");
$DEBUG .= "Read from pipe_out\n";
$atext = fread($pipe_out, 200000); // Program hangs here
程序正确启动,通过$pipe_in
正确接收输入,正确处理数据并且(因为它运行好几个月)我假设它正确地将数据输出到stdout,但是当我尝试从$pipe_out
读取,它挂起。我知道管道本身设置正确,因为如果我不打开$pipe_out
,程序就不会得到任何输入 - 这是有道理的,因为没有$pipe_out
的读者,因此管道不完整。所以我可以打开$pipe_out
,但我无法从中读取任何内容,这很奇怪。
EDIT2:
程序现在可以运行,谢谢你们 - 由于某种原因,在你从第二个管道读取之前必须关闭第一个管道:
$pipe_in = fopen($fp.$pipename, "w");
$pipe_out = fopen($fp.$pipename.'R', "r");
$DEBUG .= "Write to pipe_in\n";
$ret = fwrite($pipe_in, $in);
fclose($pipe_in);
$DEBUG .= "Read from pipe_out\n";
$atext = fread($pipe_out, 200000);
fclose($pipe_out);
unlink($fp.$pipename);
unlink($fp.$pipename.'R');
答案 0 :(得分:2)
我会为myprogram写一个小包装器,
freopen("./fifo_in","r",stdin)
freopen("./fifo_out","w",stdout)
(当然不是常数路径!),然后执行myprogram
答案 1 :(得分:0)
Korn shell支持coprocesses,我认为它可以有效地完成你的要求:从管道中读取并写入管道(可以是st进程和st进程的stdin)
http://www.dartmouth.edu/~rc/classes/ksh/coprocesses.html
答案 2 :(得分:0)
怎么样
myprogram < ./fifo_in > ./fifo_out
至于摆脱缓冲:由于你的程序直接读/写管道,缓冲不应该伤害你。
重要的一点是,写入fifo_in
的过程应该正确刷新,这样您就不必等待了。您的输出也是如此:一旦“工作单位”完成,请刷新stdout
,这将使数据可供读取输出管道的人使用。
但是你不能在myprogram
中做任何事情来让fifo_in
的作者刷新它的缓冲区。
[编辑] 要从C(没有shell的帮助)执行此操作,请使用以下代码:
- Put the names of the two pipes into local variables on the stack
- Call `fork()`. If that returns '0', then open the two fifos with `freopen()` [like Eugen suggested][1]
- Call `execve` to launch the real exec.
这是(简而言之)shell在运行命令时所做的事情。确保父进程(fork()
返回PID!= 0的进程)处理信号SIGCHLD
答案 3 :(得分:0)
也许您正在寻找named pipe?例如:
mkfifo fifo_in
作为my_program.c的测试存根,通过缓冲的fifo_in
阅读stdin
:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
char buf[80];
if (!freopen("./fifo_in", "r", stdin)) {
perror("freopen");
exit(EXIT_FAILURE);
}
while (!ferror(stdin)) {
while (fgets(buf, sizeof buf, stdin))
fputs(buf, stdout);
sleep(1);
}
return 0;
}
然后作为作者的测试,使用bash
shell:
for x in {1..10}; do
echo $x
echo $x >> fifo_in
sleep 1
done
注意: