繁体   English   中英

使用 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 行和/或第 2 行,编译/运行

./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中。

  • 这是为什么?
  • 使用fdopen的正确方法是什么?

注意 这似乎是从 C/C++ 智能写入任意文件描述符的(部分)答案的正确方法我说“部分”,因为我可以使用 C 风格的fprintf 我仍然想使用 C++ 风格的stream<<

编辑:我忘记了fclose(fp) 这“关闭”了问题的一部分。

这是为什么?

打开的 stream (“流”是打开的FILE* )是块缓冲的,因此在刷新文件之前没有任何内容写入目标。 退出应用程序会关闭所有打开的流,从而刷新 stream

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

...如果使用了两个或多个手柄,并且其中任何一个是 stream,应用程序应确保它们的动作按如下所述进行协调。 如果不这样做,结果是未定义的。

...

对于第一个手柄,适用以下第一个适用条件。 ...

  • ...

  • 如果它是一个 stream,它对写入或附加打开(但也不是对读取打开),应用程序要么执行 fflush(),要么关闭 stream。

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

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

我的猜测是什么,最有可能发生的是您的 C 标准库实现在main返回后调用fflush(fp) ,因为fd已关闭,某些内部write(3, ...)调用返回错误并且没有任何内容写入 output .

使用 fdopen 的正确方法是什么?

您提出的用法是使用fdopen的正确方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM