c - 关闭(STDOUT_FILENO)行为后到终端的标准输入输出

标签 c linux buffer stdio

我想知道为什么取消注释以下程序中的第一个 printf 语句会改变其后续行为:

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

int main() {
  //printf("hi from C \n");

  // Close underlying file descriptor:
  close(STDOUT_FILENO);

  if (write(STDOUT_FILENO, "Direct write\n", 13) != 13) // immediate error detected.
    fprintf(stderr, "Error on write after close(STDOUT_FILENO): %s\n", strerror(errno));

  // printf() calls continue fine, ferror(stdout) = 0 (but no write to terminal):
  int rtn;
  if ((rtn = printf("printf after close(STDOUT_FILENO)\n")) < 0 || ferror(stdout)) 
    fprintf(stderr, "Error on printf after close(STDOUT_FILENO)\n");
  fprintf(stderr, "printf returned %d\n", rtn);
  // Only on fflush is error detected:
  if (fflush(stdout) || ferror(stdout))
    fprintf(stderr, "Error on fflush(stdout): %s\n", strerror(errno));
}

如果没有第一个 printf,后续的 printf rtns 34 就好像没有发生错误,即使从 stdout 用户缓冲区到底层 fd 的连接已经关闭。只有在手动 fflush(stdout) 上才会报告错误。 但是随着第一个 printf 打开,下一个 printf 报告错误,正如我所料。 当然,在任何一种情况下,在关闭 STDOUT_FILENO fd 之后,都不会(通过 printf)向终端写入任何内容。

我知道首先在这里 close(STDOUT_FILENO) 是愚蠢的;这是我偶然发现的一个实验,我认为在这些领域更有知识的人可能会从中看到对我们有启发性的东西。

我在 Linux 上使用 gcc。

最佳答案

如果您strace 这两个程序,stdio 似乎可以工作,因此在第一次 写入时,它会使用 检查描述符fstat 找出连接到 stdout 的文件类型 - 如果它是终端,则 stdout 应该是行缓冲,如果它是其他东西,那么 stdout 将被 block 缓冲。如果您在第一个 printf 之前调用 close(1);,现在初始 fstat 将返回 EBADF 并且作为1 不是指向字符设备的文件描述符,stdout 是 block 缓冲的。

在我的计算机上,缓冲区大小为 8192 字节 - 可以缓冲很多字节以写入 stdout before 第一次失败将发生。


如果您取消注释第一个 printffstat(1, ...) 成功 并且 Glibc 检测到 stdout 连接到终端; stdout 设置为行缓冲,因此因为 printf after close(STDOUT_FILENO)\n 以换行结束,缓冲区将立即刷新 - 这将导致即时错误。

关于c - 关闭(STDOUT_FILENO)行为后到终端的标准输入输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44034025/

相关文章:

C 段错误核心转储

linux - 我如何使文件内容作为命令的输出?

c - fread(&buffer...) 和 fread(buffer...) 有什么区别

emacs - Emacs 中打开的分屏太多!

java - 在 Java 中为 JOGL 释放直接缓冲区 native 内存

c++ - 可变数量的参数

更改 Win32 Windows 项目中的默认窗口字体

c - 当 vlclib event_manager 通知我时在 vlclib 中播放下一首歌曲

android - 在 Linux 上为 Qt Creator 安装没有 Studio 的 Android SDK

linux - 格式错误(找不到 ldd 二进制文件)!