My question is: if the program is sleeping, what is doing the echoing?
Input and output that passes through a tty — whether it's a serial port, a virtual console, or a pty — is processed by the kernel according to the current configuration of that tty. This processing is surprisingly complex, and can include all of the following features:
- Queueing of input and output and handling flow control
- Baud rate and parity handling (for serial lines)
- Keeping track of the size of the terminal, in rows and columns
- Line buffering and editing
- Echoing input to output
- Character conversions:
- Conversion of output newlines to CR + NL sequences
- Conversion of input backspaces to DEL characters
- Conversion of tabs to spaces (off by default)
- Conversion of backspaced characters to alternate sequences, e.g.
abc^H^H^H
toabc\cba/
(off by default, was used for hardcopy terminals that can't erase characters)
- Interpreting input control sequences of various types:
- Some send signals to the foreground process, like ^C and ^Z.
- Some trigger basic line editing in the kernel, such as ^H for backspace, ^W for kill-word, and ^U for kill-line.
- Some interact with flow control, like ^S and ^Q.
In short, there's a lot of work being done by the kernel's tty layer! It's doing much more than just passing input to output.
Windows does not have a tty layer in the same sense as UNIX systems. It does have a console, but it works very differently — my understanding is that it's largely designed to emulate the text mode of the PC BIOS, not a terminal.