强制使用`exec`创建的程序来执行无缓冲的I / O [英] Force a program created using `exec` to perform unbuffered I/O

查看:106
本文介绍了强制使用`exec`创建的程序来执行无缓冲的I / O的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在C 外部程序中使用管道叉和 EXEC 。我想强制外部程序来执行缓冲I / O。下面是从我的code相关的片段至今:

I am trying to interact with an external program in C using pipe, fork and exec. I want to force the external program to perform unbuffered I/O. Here's a relevant snippet from my code so far:

...
pid = fork();
if (pid == (pid_t) 0)
{
    /* child process */

    /* make pipe connections to standard streams */             
    dup2(wpipe[0], STDIN_FILENO);
    dup2(rpipe[1], STDOUT_FILENO);

    /* close pipe endings */
    close(wpipe[0]); close(rpipe[0]);
    close(wpipe[1]); close(rpipe[1]);

    /* unbuffered I/O */
    setvbuf(stdin, NULL, _IONBF, BUFSIZ);
    setvbuf(stdout, NULL, _IONBF, BUFSIZ); 

    if (execl("path/to/some_binary", "path/to/some_binary", (char *) NULL) == -1)
    {
        fprintf(stderr, "exec failed\n");
        return EXIT_FAILURE;
    }   
    return EXIT_SUCCESS;
}
...

这不起作用,因为流不横渡 EXEC 通话生存。因此,使用 setvbuf用来来迫使无缓冲I / O不起作用,因为程序的图像( some_binary )创建标准输入和标准输出它自己的流,并且不使用我叫 setvbuf用来的流。

This does not work because streams do not survive across exec calls. So using setvbuf to force unbuffered I/O does not work, because the program image (some_binary) creates stdin and stdout streams of its own, and does not use the streams that I called setvbuf on.

该程序不工作,当我重新构建 some_binary 添加后 setvbuf用来在code调用。但如何才能,如果你没有对你传递给 EXEC 二元任何控制这样做?这怎么能做出,比如说工作,UNIX命令如 LS

The program does work when I re-build some_binary after adding the setvbuf calls in its code. But how can this be done if you do not have any control over the binary you are passing to exec? How can this be made to work for, say, a unix command like cat or ls?

推荐答案

您不能做你在一般情况下想要的东西(的 的execve(2) 任意可执行文件的...)

You cannot do what you want in the general case (unbuffering after execve(2) of arbitrary executables...)

缓冲由code(例如,通过一些的libc code相关的&LT完成C $ C>)。而code是由程序所定义的execve -ed。

Buffering is done by code (e.g. by some libc code related to <stdio.h>). And the code is defined by the program being execve-ed.

您可能或许与 LD_ preLOAD花样玩这可能会称之为 setvbuf用来(标准输入,NULL,_IONBF,BUFSIZ); 之后的的的execve (但之前 ....);但是这将与动态链接的可执行文件才能正常工作。

You might perhaps play with LD_PRELOAD tricks which might call setvbuf(stdin, NULL, _IONBF, BUFSIZ); after the execve (but before the main....); but this would work only with dynamically linked executables.

也许使用一些构造函数属性 LD_ preLOAD -ed共享对象可能的一些初始化函数有时的做的伎俩。或重新定义的printf 的fopen ,...在该共享对象...

Perhaps using some constructor function attribute in some initialization function of your LD_PRELOAD-ed shared object might sometimes do the trick. Or redefine printf, fopen, .... in that shared object...

你的评论,你做的:

用两个管道的子过程的双向通信。

two-way communication with a sub-process using two pipes.

那么你的做法是错误的。父进程应该监视两个管道,可能与复用调用如调查( 2)时,则(根据该多路复用的结果)决定读取或写入到子进程。在现实中,你需要一些事件循环:要么实现一个简单的活动的循环你自己(如与调查 [反复多次调用]重复的循环中的),或者使用一些现有的(看到 libevent的或的 libev ,或者通过一些工具如 GTK 或在 Qt的等...)

Then your approach is wrong. The parent process should monitor the two pipes, probably with a multiplexing call like poll(2), then (according to the result of that multiplexing) decide to read or to write to the child process. In reality, you want some event loop: either implement a simple event loop yourself (with e.g. poll [iteratively called many times] inside a repeated loop) or use some existing one (see libevent or libev, or the one provided by some toolkit like GTK or Qt etc...)

您还可以使用选择(2)但我建议调查<因为 C10K问题/ code>

You might also multiplex with select(2) but I recommend poll because of the C10K problem

您不会通过阅读高级Linux编程 ...

You won't lose your time by reading Advanced Linux Programming ...

另请参阅这个答案您的下一个相关的问题。

See also this answer to your next related question.

这篇关于强制使用`exec`创建的程序来执行无缓冲的I / O的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆