为何在修改终端属性的场景下仅能使用read()读取标准输入而无法使用fread()?
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_FILENOis a raw Unix file descriptor. When you useread()on it, you're making a direct system call that interacts with the terminal exactly as you've configured it withtcsetattr(). No extra buffering, no hidden assumptions—just straight-up reading whatever bytes the terminal has available.stdinis a C standard libraryFILE*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:
- 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).
- Sets
VMIN=0andVTIME=0, which makesread()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

