C fork/exec,带有非阻塞管道IO

con*_*st6 7 c fork stdout pipe nonblocking

这似乎是一件相当普遍的事情,而且我已经设法自学了我需要的一切,除了我现在有一个问题,这是我的故障排除.

int nonBlockingPOpen(char *const argv[]){
    int inpipe;
    pid_t pid;
    /* open both ends of pipe nonblockingly */
    pid = fork();

    switch(pid){
        case 0:         /*child*/
            sleep(1); /*child should open after parent has open for reading*/

            /*redirect stdout to opened pipe*/
            int outpipe = open("./fifo", O_WRONLY);
            /*SHOULD BLOCK UNTIL MAIN PROCESS OPENS FOR WRITING*/
            dup2(outpipe, 1);
            fcntl(1, F_SETFL, fcntl(1, F_GETFL) | O_NONBLOCK);

            printf("HELLO WORLD I AM A CHILD PROCESS\n");
            /*This seems to be written to the pipe immediately, blocking or not.*/
            execvp(*argv, argv);
            /*All output from this program, which outputs "one" sleeps for 1 second
             *outputs "two" sleeps for a second, etc, is captured only after the
             *exec'd program exits!
             */
            break;

        default:        /*parent*/
            inpipe = open("./fifo", O_RDONLY | O_NONBLOCK);
            sleep(2);
            /*no need to do anything special here*/
            break;
    }

    return inpipe;
}
Run Code Online (Sandbox Code Playgroud)

为什么子进程每次生成一行时都不会将其stdout写入管道?在execvp或dup2的工作方式中是否有一些我缺少的东西?我知道我对这一切的处理方式有点奇怪,但我找不到另一种以编程方式捕获闭源二进制文件输出的方法.

Pas*_*uoq 3

我猜你只能在退出后获得 exec'd 程序的输出,因为它不会在每条消息后刷新。如果是这样,您从外部无能为力。

我不太确定这与您问题中阻塞和非阻塞 I/O 之间的选择有何关系。非阻塞写入可能完全或部分失败:调用不会阻塞程序直到管道中有可用空间,而是立即返回并表示它无法写入应有的所有内容。非阻塞 I/O 既不会使缓冲区变大,也不会强制刷新输出,并且某些程序可能对其支持不佳。

您不能强制刷新正在执行的纯二进制程序。如果您认为非阻塞 I/O 是该问题的解决方案,那么抱歉,但恐怕它是相当正交的。

编辑:好吧,如果 exec'd 程序仅使用 libc 提供的缓冲(不实现自己的)并且是动态链接的,则可以通过将其链接到刷新每次写入的修改后的 libc 来强制它刷新。这将是一个孤注一掷的措施。仅当其他一切都失败时才尝试。