从C程序中执行程序
我应该如何在我的C
程序中运行另一个程序?我需要能够将数据写入已启动程序的" STDIN"中(并可能从其" STDOUT"中读取)
我不确定这是否是标准的C函数。我需要应该在Linux下工作的解决方案。
解决方案
回答
我们想使用popen
。它为我们提供了一个单向管道,我们可以使用该管道访问程序的stdin和stdout。
popen是现代unix和类unix操作系统的标准配置,其中Linux是其中之一:-)
类型
man popen
在终端上阅读有关它的更多信息。
编辑
popen是产生单向还是双向管道取决于实现。在Linux和OpenBSD中,popen
产生单向管道,它们是只读或者只写的。在OS X上,FreeBSD和NetBSDpopen
产生双向管道。
回答
我想你可以用
freopen
为了这 。
回答
- 用
pipe(...)
创建两个管道,一个用于stdin
,一个用于stdout
。 fork(...)
过程。- 在子进程中(" fork(...)"返回0的子进程)," dup(...)"将管道传递到" stdin" /
stdout
。 - exec [v] [e]子进程中要启动的程序文件。
- 在父进程(" fork"返回孩子的PID的父进程)中,执行一个循环,该循环从孩子的" stdout"(" select(...)"或者" poll(...)"中读取)读(...)
)到缓冲区中,直到子项终止(
waitpid(...)`)。 - 最终如果期望孩子给孩子提供在" stdin"上的输入。
- 完成后,关闭管道。
回答
我们可以使用系统调用,阅读系统的联机帮助(3)
回答
我不同意内森·费尔曼(Nathan Fellman)的观点,尽管这个问题是相关的,但另一个问题不是重复的。
对于简单的单向通信,popen()是一个不错的解决方案。但是,它对于双向通信没有用。
国际海事组织(Imjorge)(Jorge Ferreira)给出了双向通信的大部分答案(80%?),但省略了一些关键细节。
- 父进程关闭用于向子进程发送消息的管道的读取端至关重要。
- 子进程关闭用于向子进程发送消息的管道的写端至关重要。
- 父进程关闭用于向父进程发送消息的管道的写端至关重要。
- 子进程关闭用于向父进程发送消息的管道的读取端至关重要。
如果不关闭管道未使用的端部,则在其中一个程序终止时,我们将不会表现出明智的行为。例如,子级可能正在从其标准输入中进行读取,但是除非在子级中关闭管道的写端,否则它将永远不会得到EOF(读取的零字节),因为它仍然具有打开的管道并且系统认为可能有时会写到该管道,即使该管道当前已挂起,正在等待从中读取某些内容。
写入过程应考虑是否处理在没有读取过程的管道上写入时给出的SIGPIPE信号。
我们必须了解管道容量(取决于平台,并且可能只有4KB),并设计程序以避免死锁。
回答
我为其他人写了一些示例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); }