read()函数返回值与O_NONBLOCK设置不符的技术咨询
read() Behavior Doesn't Match the Manual Let's cut to the chase: the core issue here is that you're testing with a regular file, but the POSIX manual rules you're referencing only apply to stream-oriented file descriptors (like sockets, character devices, or pseudoterminals)—not regular files.
First, Let's Clarify Regular File Behavior
Regular files have a fixed, seekable size. When you call read() on a regular file:
- If you're at the end of the file (EOF),
read()will always return0immediately, regardless of whetherO_NONBLOCKis set. There's no "waiting for more data" scenario here because regular files don't dynamically receive new data unless another process appends to them—and even then, you'd need to re-read from the new offset, not just keep callingread()at the EOF position. - If there is data available,
read()will read as much as possible (up to your buffer size) and return the number of bytes read, again ignoringO_NONBLOCK.
The Manual Rules Apply to Special File Types
The manual's description of O_NONBLOCK behavior for "files that support non-blocking reads (excluding pipes/FIFOs)" refers to file descriptors where data arrives dynamically, such as:
- Network sockets (TCP/UDP)
- Character devices (e.g.,
/dev/tty, serial ports) - Pseudoterminals (PTYs)
- Other stream-based I/O channels where data isn't pre-stored in a fixed file
For these types:
- If
O_NONBLOCKis set and no data is available,read()returns-1witherrno = EAGAIN - If
O_NONBLOCKis not set,read()blocks until data arrives - If data is already available,
O_NONBLOCKhas no effect
A Quick Note on Your Code
In your second method, you're actually clearing the O_NONBLOCK flag with saved_flags & ~O_NONBLOCK—that sets the descriptor to blocking mode, not non-blocking. To enable non-blocking, you'd need to use saved_flags | O_NONBLOCK. But even if you fixed that, it wouldn't change the behavior for your regular file test case.
How to Verify the Manual's Rules
To see the expected non-blocking behavior, test with a stream-oriented descriptor. For example:
- Open
/dev/tty(your terminal) withO_RDONLY - Set
O_NONBLOCKusingfcntl() - Call
read()without typing anything—you'll get-1witherrno = EAGAIN - Clear
O_NONBLOCKand callread()again—the call will block until you type input
内容的提问来源于stack exchange,提问作者guang chen

