我正在尝试写stdin并从外部程序中从stdout(和stderr)读取,而无需更改代码。
我尝试使用命名管道,但是直到程序终止并且stdin仅在第一个输入上起作用(然后cin为null)时,stdout才会显示。
我试过使用/proc/[pid]/fd,但这仅从终端而不是从程序进行写入和读取。
我已经尝试为此编写一个字符设备文件,并且该文件可以工作,但是一次只能一个程序(这一次需要为多个程序工作)。
在这一点上,据我所知,我可以编写可在多个程序之间复用io的驱动程序,但我认为这不是“正确的”解决方案。
其主要目的是通过Web界面查看程序的提要。我敢肯定一定有办法做到这一点。有没有我没尝试过的东西?
最佳答案
这样做的典型方法是:
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
标志,即使标准输出不是终端,也可以强制其对输出进行行缓冲。如果您的外部程序具有这样的选项,则应该使用它。如果没有,仍然可以更改缓冲行为,但是您必须使用一些偷偷摸摸的技巧-有关操作方法,请参见this question和this question。