04-在备选的IO模型中采用非阻塞IO
63.1.2 在备选的I/O模型中采用非阻塞I/O
非阻塞I/O(O_NONBLOCK标志)常和本章中所描述的I/O模型一起使用。下面列出了一些例子,以说明为什么这么做会很有用。
- 如同上一节所述,非阻塞I/O通常和提供有边缘触发通知机制的I/O模型一起使用。
- 如果多个进程(或线程)在同一个打开的文件描述符上执行I/O操作,那么从某个特定进程的角度来看,文件描述符的就绪状态可能会在通知就绪和执行后续I/O调用之间发生改变。结果就是一个阻塞式的I/O调用将阻塞,从而防止进程检查其他的文件描述符。(这种情况会发生在本章所描述的所有I/O模型上,无论它们采用的是水平触发还是边缘触发。)
- 尽管水平触发模式的API比如select()或poll()通知我们流式套接字的文件描述符已经写就绪了,如果我们在单个write()或send()调用中写入足够大块的数据,那么该调用将阻塞。
- 在非常罕见的情况下,水平触发型的 API 比如 select()和 poll(),会返回虚假的就绪通知——它们会错误地通知我们文件描述符已经就绪了。这可能是由内核bug造成的,或非普通情况下的设计方案所期望的行为。
[Stevens et al., 2004]中16.6节介绍了一个BSD系统上的监听套接字的虚假就绪通知例子。如果客户端先连接到服务器端的监听套接字上,然后再重置连接,服务器端的select()调用在这两个事件之间将提示监听套接字为可读就绪,但随后当客户端重置连接后,服务器端的accept()调用会阻塞。