41. 非阻塞IO

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Function_Dou/article/details/89959151

前面我们所使用的IO都是阻塞式的, 当然, 默认也是阻塞式的. 不过我们也可以设置文件描述符将阻塞式变为非阻塞式. 我们为什么会将阻塞式转为非阻塞式呢? 肯定是有好处的, 而本节就先简单介绍一下关于非阻塞式.


阻塞式

先来了解一下阻塞式.

阻塞式 : 进程运行到阻塞式的函数时会被投入睡眠切换执行其他程序, 直到被中断或者被唤醒才会切换回程序继续执行.

阻塞式的问题 :

  1. 对于CPU来说IO操作是最耗费时间的, 而等待的过程中并不能(或者不能高效)的做其他处理操作, 导致CPU的利用率低下. 在通信过程中, 基本上过半的时间都被IO阻塞, 而CPU在这段时间都是空闲无所事事的.
  2. 上下文切换耗时. 投入睡眠后将重新加载其他程序, 唤醒后又必须重新加载回来. 每次睡眠的时间如果每次都很短, 结果导致大部分时间都用来上下文切换, 而CPU并没有高效的被利用.

采用非阻塞式可以使程序不会投入睡眠区等待也不用上下文切换, 而是继续执行后续的指令, 充分利用CPU.


非阻塞式IO

先来介绍一下四种阻塞式IO.

  • 输入操作 ( 如 : read, readv, recv, recvfrom, recvmsg )
    TCP 和 UDP 套接字 :

    • 阻塞 : 如果接收缓冲区为空, 则调用会导致调用的进程休眠, 直到有数据后被唤醒.

    • 非阻塞 : 函数立即返回(返回-1), 并置 errno 为 EAGAIN 后继续执行.

  • 输出操作 ( 如 : write, writev, send, sendto, sendmsg )

    阻塞 :

    • TCP : 如果发送缓冲区满了, 调用进程将会被阻塞.

    • UDP : 没有发送缓冲区,但可能会因为其它原因而阻塞.

    非阻塞 : 函数立即返回(返回-1), 并置errno 为 EAGAIN 后继续执行.

  • accept函数

    • 阻塞 : 如果没有新的连接
    • 非阻塞 : 函数立即返回(返回-1), 并置errno 为 EAGAIN 后继续执行.
  • connect函数

    • 阻塞 : connect 函数要对端确认 ACK 后才返回(成功/失败).
    • 非阻塞 : connect函数发送 SYN 后立即返回(失败), 并置errno 为 EINPROGRESS , 后续通过某些操作判断是否连接成功.

注意 : 非阻塞可以避免程序睡眠和切换的好处, 但也使代码编写更加复杂.

非阻塞式IO的系统调用总是立即返回, 不管是否执行成功(读取倒数据).


小结

  • 阻塞式问题
  • 非阻塞式情况
  • 非阻塞式问题

猜你喜欢

转载自blog.csdn.net/Function_Dou/article/details/89959151