【Linux网络编程】网络编程常见概念
阻塞与非阻塞
阻塞 IO:执行的系统调用可能因为无法立即完成而被操作系统挂起,直到等待的事件发生为止。如服务端的 accept(),在客户端未 connect() 时,其一直处于阻塞状态直至发生为止,但我们可以对监听的文件描述符通过 fcntl() 设置 O_NONBLOCK ,这时就能将阻塞 IO 改为非阻塞 IO。
非阻塞 IO:执行的系统调用总是立即返回,不管事件是否已经发生。如果事件没有立即发生,系统调用就返回 -1,和出错的情况一样。此时必须依据 errno 来区分这两种情况,对accept()、send() 和 recv() 而言,事件未发生时 errno 通常被设置为 EAGAIN 或者 EWOULDBLOCK,对 connect() 则 errno 被设置为 EINPROGRESS。
同步与异步
同步 IO:要求用户代码自行执行 IO 操作,即将数据从内核缓冲区读入用户缓冲区,或将数据从用户缓冲区读入内核缓冲区,而阻塞 IO、IO 复用和信号驱动 IO 等都属于同步 IO。
异步 IO:用户可以直接对 IO 执行读写操作,这些操作告诉内核用户读写缓冲区的位置,以及 IO 操作完成后内核通知应用程序的方式,即由内核完成 IO 操作。
所以我们也可以这样认为:同步 IO 向应用程序通知的是 IO 就绪事件,而异步 IO 则向应用程序通知的是完成事件。
陈硕:在处理 IO 的时候,阻塞和非阻塞都是同步的 IO,只有使用了特殊的 API 才是异步 IO。
如下则展示了阻塞 / 非阻塞与同步 / 异步的关系: