我正在C中的模拟文件系统上实现管道(主要是C) . 它需要在主机shell中运行命令,但在模拟文件系统上执行管道本身 .
我可以通过 pipe()
, fork()
和 system()
系统调用来实现这一点,但我更喜欢使用 popen()
(它处理创建管道,分支进程,并将命令传递给shell) . 这可能是不可能的,因为(我认为)我需要能够从管道的父进程写入,在子进程端读取,从子进程写回输出,最后从父进程读取该输出 . 我的系统上的 popen()
的手册页说明了双向管道,但是我的代码需要在一个只支持单向管道的旧版本的系统上运行 .
With the separate calls above, I can open/close pipes to achieve this. Is that possible with popen()?
对于一个简单的例子,要运行 ls -l | grep .txt | grep cmds
,我需要:
-
打开一个管道和进程以在主机上运行
ls -l
;读回它的输出 -
将
ls -l
的输出传回我的模拟器 -
打开管道并进程以在
ls -l
的管道输出上的主机上运行grep .txt
-
将此输出传回模拟器(卡在此处)
-
打开管道并进程以在
grep .txt
的管道输出上的主机上运行grep cmds
-
将此输出传回模拟器并打印出来
man popen
从Mac OS X:
popen()函数通过创建双向管道,分叉和调用shell来“打开”一个过程 . 由父进程中先前的popen()调用打开的任何流都将在新的子进程中关闭 . 从历史上看,popen()是用单向管道实现的;因此,popen()的许多实现只允许mode参数指定读或写,而不是两者 . 由于popen()现在使用双向管道实现,因此mode参数可以请求双向数据流 . mode参数是一个指向以null结尾的字符串的指针,该字符串必须为'r'表示读取,'w'表示写入,或'r'表示读写 .
5 回答
你似乎回答了自己的问题 . 如果您的代码需要在不支持
popen
打开双向管道的旧系统上工作,那么您将无法使用popen
(至少不能使用提供的那个) .真正的问题是关于旧系统的确切功能 . 特别是,他们的
pipe
支持创建双向管道吗?如果他们有pipe
可以创建一个双向管道,但popen
没有't, then I'编写代码的主流以使用popen
与双向管道,并提供popen
的实现,可以使用一个双向管道,可以在一个管道中编译在需要的地方使用如果你需要支持足够大的系统
pipe
只支持单向管道,那么你自己就完全坚持使用pipe
,fork
,dup2
等 . 我可能仍然将它包装在一个几乎像popen
的现代版本的函数中,但不是返回一个文件句柄,而是填充一个带有两个文件句柄的小结构,一个用于孩子的stdin
,另一个用于孩子的stdout
.我建议您编写自己的功能来为您进行管道/分叉/系统管理 . 您可以让函数生成一个进程并返回读/写文件描述符,如...
您可以在其中添加所需的任何功能 .
POSIX规定popen()呼叫不是为了提供双向通信而设计的:
任何可移植的代码都不会做出任何假设 . BSD
popen()
与您的问题描述的类似 .另外,管道与套接字不同,每个管道文件描述符都是单向的 . 您必须创建两个管道,一个为每个方向配置 .
无需在每个进程中创建两个管道并浪费文件描述符 . 只需使用套接字即可 . https://stackoverflow.com/a/25177958/894520
在其中一个netresolve后端我正在与一个脚本交谈,因此我需要写入
stdin
并从其stdout
读取 . 以下函数执行一个命令,其中stdin和stdout重定向到管道 . 您可以使用它并根据自己的喜好进行调整 .https://github.com/crossdistro/netresolve/blob/master/backends/exec.c#L46
(我用了相同的代码在popen simultaneous read and write)