【发布时间】:2010-09-09 09:48:22
【问题描述】:
我应该如何从我的C 程序中运行另一个程序?我需要能够将数据写入已启动程序的STDIN(可能从它的STDOUT中读取)
我不确定这是否是标准 C 函数。我需要能在 Linux 下工作的解决方案。
【问题讨论】:
我应该如何从我的C 程序中运行另一个程序?我需要能够将数据写入已启动程序的STDIN(可能从它的STDOUT中读取)
我不确定这是否是标准 C 函数。我需要能在 Linux 下工作的解决方案。
【问题讨论】:
【讨论】:
popen 允许单向管道:developer.apple.com/legacy/library/documentation/Darwin/…。 *BSD 似乎也是如此。
不久前,我为其他人编写了一些示例 C 代码,展示了如何执行此操作。这是给你的:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void error(char *s);
char *data = "Some input data\n";
main()
{
int in[2], out[2], n, pid;
char buf[255];
/* In a pipe, xx[0] is for reading, xx[1] is for writing */
if (pipe(in) < 0) error("pipe in");
if (pipe(out) < 0) error("pipe out");
if ((pid=fork()) == 0) {
/* This is the child process */
/* Close stdin, stdout, stderr */
close(0);
close(1);
close(2);
/* make our pipes, our new stdin,stdout and stderr */
dup2(in[0],0);
dup2(out[1],1);
dup2(out[1],2);
/* Close the other ends of the pipes that the parent will use, because if
* we leave these open in the child, the child/parent will not get an EOF
* when the parent/child closes their end of the pipe.
*/
close(in[1]);
close(out[0]);
/* Over-write the child process with the hexdump binary */
execl("/usr/bin/hexdump", "hexdump", "-C", (char *)NULL);
error("Could not exec hexdump");
}
printf("Spawned 'hexdump -C' as a child process at pid %d\n", pid);
/* This is the parent process */
/* Close the pipe ends that the child uses to read from / write to so
* the when we close the others, an EOF will be transmitted properly.
*/
close(in[0]);
close(out[1]);
printf("<- %s", data);
/* Write some data to the childs input */
write(in[1], data, strlen(data));
/* Because of the small amount of data, the child may block unless we
* close it's input stream. This sends an EOF to the child on it's
* stdin.
*/
close(in[1]);
/* Read back any output */
n = read(out[0], buf, 250);
buf[n] = 0;
printf("-> %s",buf);
exit(0);
}
void error(char *s)
{
perror(s);
exit(1);
}
【讨论】:
pipe(...) 创建两个管道,一个用于stdin,一个用于stdout。 fork(...) 进程。fork(...) 返回 0 的那个)dup (...) 到stdin/stdout 的管道。exec[v][e]子进程中要启动的programm文件。fork)返回子进程的 PID)执行一个循环,从子进程的stdout(select(...) 或poll(...),read(...))读取到缓冲区,直到
孩子终止(waitpid(...))。 stdin 上提供输入。close(...) 管道。【讨论】:
对于简单的单向通信,popen() 是一个不错的解决方案。但是,它对双向通信没有用处。
IMO,imjorge (Jorge Ferreira) 给出了双向通信的大部分答案(80%?) - 但省略了一些关键细节。
如果您不关闭未使用的管道末端,那么当其中一个程序终止时,您不会获得明智的行为;例如,孩子可能正在从其标准输入读取,但除非管道的写入端在孩子中关闭,否则它将永远不会获得 EOF(读取的零字节),因为它仍然打开管道并且系统认为它有时可能会开始写入该管道,即使它当前挂起等待从中读取内容。
写入进程应考虑是否处理在没有读取进程的管道上写入时发出的 SIGPIPE 信号。
您必须了解管道容量(取决于平台,可能只有 4KB)并设计程序以避免死锁。
【讨论】:
可以使用系统调用,阅读manpage for system(3)
【讨论】:
我认为你可以使用
freopen
为此。
【讨论】: