我正在尝试写入stdin并从外部程序读取stdout(和stderr),而不更改代码。
我尝试过使用命名管道,但是直到程序终止并且stdin仅对第一个输入起作用(然后cin为null)才会显示stdout。
我尝试过使用/ proc / [pid] / fd,但只能从终端写入和读取而不是程序。
我已经尝试为此编写一个字符设备文件并且它可以工作,但一次只能有一个程序(这需要一次为多个程序工作)。
此时,据我所知,我可以编写驱动程序,在多个程序中复用io,但我不认为这是“正确”的解决方案。
这样做的主要目的是通过Web界面查看程序的订阅源。我确信必须要做到这一点。有什么我以前没有尝试过的吗?
答案 0 :(得分:5)
这样做的典型方法是:
pipe(2)
系统调用为新进程的标准流创建匿名管道(非命名管道)fork(2)
以生成子进程close(2)
父节点和子节点中管道的适当末端(例如,对于stdin管道,关闭父节点中的读取端并关闭子节点中的写入节点;反之亦然,对于stdout和stderr管道)dup2(2)
将管道文件描述符复制到文件描述符0,1和2,然后close(2)
剩余的旧描述符exec(3)
子进程中的外部应用程序select(2)
系统调用等待,直到可以不受阻塞地读取/写入其中一个流,然后处理该流。即使您正确执行此操作,您仍可能无法立即看到程序的输出。这通常是由于缓冲标准输出。通常,当stdout进入终端时,它是行缓冲的 - 它会在每个换行符写入后刷新。但是当stdout是一个管道(或者其他任何不是终端的东西,比如文件或套接字)时,它是完全缓冲的,只有在程序输出完整缓冲区的数据(例如4 KB)时才会被写入。
许多程序都有命令行选项来改变缓冲行为。例如,grep(1)
具有--line-buffered
标志,即使stdout不是终端,也强制它对其输出进行行缓冲。如果您的外部程序有这样的选项,您应该使用它。如果没有,仍然可以改变缓冲行为,但你必须使用一些偷偷摸摸的技巧 - 请参阅this question和this question了解如何做到这一点。