我正在C++中的一个模拟文件系统上实现管道(主要是用C)。它需要在主机外壳中运行命令,但在模拟的文件系统上执行管道本身。
我可以通过pipe()、fork()和system()系统调用来实现这一点,但我更喜欢使用popen() (它处理创建管道、分叉进程和将命令传递给shell)。这可能是不可能的,因为(我认为)我需要能够从管道的父进程写入,在子进程结束时读取,从子进程写入输出,最后从父进程读取输出。我的系统上的popen()手册页说双向管道是可能的,但是我的代码需要运行在一个只支持单向管道的旧版本的系统上。
与上面的单独调用,我可以打开/关闭管道来实现这一点。对popen()**?**来说,这有可能吗?
对于一个简单的例子,要运行ls -l | grep .txt | grep cmds,我需要:
ls -l;将其输出读回ls -l的输出输送回我的模拟器grep .txt输出的管道上在主机上运行ls -lgrep cmds输出的管道上在主机上运行grep .txtman popen
来自Mac:
popen()函数通过创建双向管道、分叉和调用shell来“打开”进程。父进程中以前的popen()调用打开的任何流都将在新的子进程中关闭。历史上,popen()是用单向管道实现的;因此,许多popen()实现只允许模式参数指定读或写,而不是两者都指定。因为popen()现在是使用双向管道实现的,所以模式参数可能请求双向数据流。模式参数是指向以空结尾的字符串的指针,该字符串必须为“r”用于读取,“w”用于写入,或“r+”用于读取和写入。
发布于 2010-10-07 17:32:18
你似乎已经回答了你自己的问题。如果您的代码需要在不支持popen打开双向管道的旧系统上工作,那么您将无法使用popen (至少不能使用所提供的)。
真正的问题是有关较旧系统的确切能力。特别是,他们的pipe是否支持创建双向管道?如果他们有一个可以创建双向管道的pipe,但没有创建双向管道的popen,那么我将编写代码的主要流,以便在双向管道中使用popen,并提供一个popen的实现,该实现可以使用在需要时编译的双向管道。
如果您需要支持足够老的系统,使pipe只支持单向管道,那么您几乎只能自己使用pipe、fork、dup2等。我可能仍然会把它封装在一个几乎像现代版本的popen的函数中,但是不是返回一个文件句柄,而是用两个文件句柄填充一个小结构,一个用于子文件的stdin,另一个用于子文件的stdout。
发布于 2010-10-07 17:55:42
我建议写你自己的函数来帮你做管道/分叉/系统。可以让函数生成一个进程并返回读/写文件描述符,如.
typedef void pfunc_t (int rfd, int wfd);
pid_t pcreate(int fds[2], pfunc_t pfunc) {
/* Spawn a process from pfunc, returning it's pid. The fds array passed will
* be filled with two descriptors: fds[0] will read from the child process,
* and fds[1] will write to it.
* Similarly, the child process will receive a reading/writing fd set (in
* that same order) as arguments.
*/
pid_t pid;
int pipes[4];
/* Warning: I'm not handling possible errors in pipe/fork */
pipe(&pipes[0]); /* Parent read/child write pipe */
pipe(&pipes[2]); /* Child read/parent write pipe */
if ((pid = fork()) > 0) {
/* Parent process */
fds[0] = pipes[0];
fds[1] = pipes[3];
close(pipes[1]);
close(pipes[2]);
return pid;
} else {
close(pipes[0]);
close(pipes[3]);
pfunc(pipes[2], pipes[1]);
exit(0);
}
return -1; /* ? */
}你可以在里面添加你需要的任何功能。
发布于 2010-10-07 17:29:20
POSIX规定,popen()调用不是为提供双向通信而设计的:
popen()的模式参数是一个指定I/O模式的字符串:
任何可移植代码都不会做出任何假设。BSD popen()类似于您的问题描述的内容。
此外,管道不同于套接字,每个管道文件描述符都是单向的.您必须创建两个管道,一个为每个方向配置。
https://stackoverflow.com/questions/3884103
复制相似问题