默认情况下,对一个 fd 做 read()
write()
时,如果没有合适的数据读取、缓冲区空间不足以写入相应内容时,进程会阻塞住等待 I/O 完成,操作系统会把进程置为 sleep 状态并执行其他进程。
这在 server 场景下很不实用,因为一个 server 要处理大量的连接(即大量的 fd),如果读写一个 fd 就被 block 住,就无法处理大量的连接。
于是 Linux 提供了一个 flag O_NONBLOCK
。对 fd 设置上该 flag 后,读写时如果数据未 ready,则操作系统不再阻塞,而是返回 EAGAIN
或是 EWOULDBLOCK
错误(这两者可以认为是一样的)。
如何对 fd 设置上 O_NONBLOCK
呢?
- 对于通过
open()
获得的 fd,在open()
的参数中传入O_NONBLOCK
- 对于不是通过
open()
的,比如 FIFO、socket 等,使用fcntl()
来设置
非阻塞的 fd,如果不配合 I/O 多路复用 是没啥意义的。因为:
- 如果你用一个无限的循环不停去查询该 fd 的状态,会浪费大量的 CPU
- 如果你在循环中加入等待间隔,则对 fd 的处理不够及时
这都会使性能无法被利用好。