fdopen 的正确使用方法

Correct way of using fdopen

我的意思是将文件描述符与文件指针相关联,并将其用于写入。 我把程序io.cc放在下面:

int main() {
    ssize_t nbytes;
    const int fd = 3;
    char c[100] = "Testing\n";
    nbytes = write(fd, (void *) c, strlen(c));     // Line #1
    FILE * fp = fdopen(fd, "a");
    fprintf(fp, "Writing to file descriptor %d\n", fd);
    cout << "Testing alternate writing to stdout and to another fd" << endl;
    fprintf(fp, "Writing again to file descriptor %d\n", fd);
    close(fd);     // Line #2
    return 0;
}

我可以交替注释行 1 and/or 2, compile/run

./io 3> io_redirect.txt

并检查io_redirect.txt的内容。 每当第 1 行未被注释时,它会在 io_redirect.txt 中生成预期的行 Testing\n。 如果第 2 行被注释,我得到预期的行

Writing to file descriptor 3
Writing again to file descriptor 3

io_redirect.txt 中。 但是如果没有注释,这些行不会出现在 io_redirect.txt.

注意。 这似乎是对 Smart-write to arbitrary file descriptor from C/C++ 的(部分)答案的正确方法 我说 "partial" 因为我可以使用 C 风格 fprintf。 我仍然想也使用 C++ 风格 stream<<.

编辑: 我忘记了 fclose(fp)。 "closes" 问题的一部分。

Why is that?

打开的流(“流”是一个打开的 FILE*)是块缓冲的,因此在刷新文件之前不会将任何内容写入目标。退出应用程序 closes all open streams, which flushes the stream.

因为您在刷新流之前关闭了底层文件描述符,所以您的程序的行为是未定义的。我真的建议您阅读 posix 2.5.1 Interaction of File Descriptors and Standard I/O Streams(尽管如此,它是用一种可怕的语言编写的),其中:

... if two or more handles are used, and any one of them is a stream, the application shall ensure that their actions are coordinated as described below. If this is not done, the result is undefined.

...

For the first handle, the first applicable condition below applies. ...

  • ...

  • If it is a stream which is open for writing or appending (but not also open for reading), the application shall either perform an fflush(), or the stream shall be closed.

“句柄”是文件描述符或流。 “活动句柄”是您使用的最后一个句柄。

fp 流是为追加到文件描述符 3 而打开的活动句柄。因为 fp 是一个活动句柄并且未被刷新,并且您使用 close(fd) 将活动句柄切换为 fd,所以您的程序的行为是未定义的。

我的猜测是,最有可能发生的是,您的 C 标准库实现在 main returns 之后调用 fflush(fp),因为 fd 已关闭,一些内部 write(3, ...) 调用 returns 出错,没有任何内容写入输出。

What is the correct way of using fdopen?

您提供的用法是fdopen.

的正确使用方法