将文件描述符从“open_memstream”传递到“dup2”

Passing a file descriptor from `open_memstream` to `dup2`

我正在尝试将 exec()ed 函数的输出重定向到缓冲区,所以我会尝试使用 open_memstream 来处理动态缓冲

我把这个放在一起测试一下:

#include <stdio.h>
#include <unistd.h>

int main() {
    char* buffer;
    size_t buffer_len;
    FILE* stream = open_memstream(&buffer, &buffer_len);
    if(!stream) perror("Something went wrong with `open_memstream`!");
    fflush(stream);

    puts("Start");

    if(dup2(fileno(stream), STDOUT_FILENO) == -1) perror("Something went wrong!");

    puts("Internal");

    fclose(stream);

    FILE* f = fopen("out.txt", "w+");
    fputs(buffer, f);
    fclose(f);
}

但是 运行 它在 dup2 上给了我错误 bad file descriptor,这不应该是这样的,因为 open_memstream 没有 return NULL 它应该在错误时执行的操作。

关于 open_memstream 的实现是否有一些东西使得操纵其底层描述符变得不可行?还是我只是愚蠢而错误地使用了一个函数?

提前为任何帮助干杯,如果 不可能用 open_memstream 做,有没有办法用 FILE* 处理它而不是直接使用 fds?

您应该在 每个 可能出错的操作之后检查 return 值(以及随后的 errno)。在这里,您缺少对 fileno(stream) return 值的检查。

FILE* stream = open_memstream(&buffer, &buffer_len);
if(!stream) perror("Failed to open_memstream");

int fd = fileno(stream);
if (fd == -1) {
    perror("Failed to get memstream fileno");
    exit(1);
}

当您添加以上内容时,您的程序将失败并显示消息

Failed to get memstream fileno: Bad file descriptor

问题的评论中已经解释了失败的原因。

查看带有 O_TMPFILE 参数的 open,或查看 memfd_create,它与 open_memstream 相似,但 return 是一个文件描述符。

这些方法迫使您放弃 &buffer&buffer_len 带来的便利。但实际上什么都没有丢失。可以使用 lseek 了解 tmp 文件大小,然后 mmap 将其作为内存缓冲区进行访问,从而恢复所有便利。