gpt4 book ai didi

c - 强制使用 `exec` 创建的程序执行无缓冲 I/O

转载 作者:太空宇宙 更新时间:2023-11-03 23:50:35 26 4
gpt4 key购买 nike

我正在尝试使用 pipeforkexec 与 C 中的外部程序进行交互。我想强制外部程序执行无缓冲的 I/O。到目前为止,这是我的代码中的相关片段:

...
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) 创建它自己的 stdin 和 stdout 流,并且不使用我调用了 setvbuf

当我在其代码中添加 setvbuf 调用后重新构建 some_binary 时,该程序确实有效。但是,如果您对传递给 exec 的二进制文件没有任何控制权,如何做到这一点呢?这如何才能适用于像 catls 这样的 unix 命令?

最佳答案

在一般情况下你不能做你想做的事(在任意可执行文件的 execve(2) 之后取消缓冲...)

缓冲由代码完成(例如,由与 libc 相关的一些 <stdio.h> 代码)。代码由程序定义为 execve -编辑。

你也许可以玩 LD_PRELOAD tricks可能会调用 setvbuf(stdin, NULL, _IONBF, BUFSIZ); execve 之后(但在 main ....之前);但这只适用于动态链接的可执行文件。

也许使用一些 constructor function attribute在你的 LD_PRELOAD 的一些初始化函数中-ed 共享对象可能有时 可以达到目的。或者重新定义 printf , fopen , .... 在那个共享对象中...

附录

您评论说您这样做了:

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

那你的做法是错误的。父进程应该监视这两个管道,可能使用类似 poll(2) 的多路复用调用。 ,然后(根据多路复用的结果)决定读取或写入子进程。实际上,您想要一些 event loop : 自己实现一个简单的事件循环(例如poll [在重复的循环中多次迭代调用)或使用一些现有的一个(参见 libeventlibev ,或由一些工具包提供的一个,如 GTKQt 等...)

您也可以使用 select(2) 进行多路复用但我推荐poll因为 C10K problem

阅读 Advanced Linux Programming 不会浪费您的时间...

另见 this answer到你的下一个相关问题。

关于c - 强制使用 `exec` 创建的程序执行无缓冲 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20571614/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com