You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在修改终端属性的场景下仅能使用read()读取标准输入而无法使用fread()?

Why fread() Fails Here But read() Works

Great question—this is a common gotcha when mixing raw Unix file descriptor calls with C standard library stdio functions. Let's break down what's going on:

The Key Difference Between STDIN_FILENO and stdin

You're right that both ultimately point to the same standard input, but they're very different layers of abstraction:

  • STDIN_FILENO is a raw Unix file descriptor. When you use read() on it, you're making a direct system call that interacts with the terminal exactly as you've configured it with tcsetattr(). No extra buffering, no hidden assumptions—just straight-up reading whatever bytes the terminal has available.
  • stdin is a C standard library FILE* stream built on top of that file descriptor. It adds its own buffering (line buffering by default for terminal inputs) and keeps track of internal state about how input should be handled.

Why Your Terminal Settings Break fread()

Your settings() function does two critical things to the terminal:

  1. Switches it to non-canonical mode (turns off the terminal's built-in line buffering, so input is available immediately instead of waiting for a newline).
  2. Sets VMIN=0 and VTIME=0, which makes read() return right away even if no input is present.

The problem is that the stdio library has no idea you've changed the terminal's mode. It still expects the terminal to operate in canonical mode—waiting for full lines of input before making them available to fread(). Even worse, stdio's internal buffer is out of sync with the terminal's new state. So fread() will sit there waiting for input that never comes in the format it expects.

Why read() Works Fine

read() doesn't have any of stdio's extra baggage. It uses the terminal settings you explicitly configured, so it reads bytes exactly as they arrive—no waiting for newlines, no internal buffering getting in the way. It's a direct, unfiltered interface to the terminal's input.

If You Want to Use fread() Anyway

If you really need to use fread() instead of read(), you can disable stdio's internal buffering for stdin after modifying the terminal settings. This makes fread() act more like a raw system call:

// Add this after calling settings() in main()
setvbuf(stdin, NULL, _IONBF, 0);

This tells the stdio library not to buffer input for stdin, so fread() will directly fetch bytes from the underlying file descriptor, matching the behavior of read().

内容的提问来源于stack exchange,提问作者pattydaone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 12:42:43