TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

同步,异步,阻塞,非阻塞

术语

  • NIO(Non-blocked IO)

  • BIO(blocked IO)

  • AIO(asynchronous I/O)

概念

阻塞/非阻塞

阻塞和非阻塞说的是程序在等待调用结果时的状态,取决与CPU会不会在进程时间片未用尽的情况下进行进程切换,将进程变成非运行状态(挂起进程)。

阻塞调用

阻塞.jpg

accept队列为空的时候,进程被挂起,等accept队列不为空了,cpu再唤醒进程

非阻塞调用

不管accept队列内部情况,每次系统调用accept函数都会立即得到一个返回值,进程不会被挂起

非阻塞.jpg

可能阻塞的系统调用:

  • 输入操作:read, readv, recv, recvfrom, recvmsg
  • 输出操作:write, writev, send, sendto, sendmsg
  • 接收外来连接:accept
  • 发起外出连接:connect

阻塞IO/非阻塞IO

因为IO操作导致的进程被cpu挂起,唤醒即是阻塞IO和非阻塞IO


同步/异步

同步: A发出一个’请求’后,一直等待,直到请求执行结束,得到请求的返回值(B发来的)

异步: A发出一个’请求’后,直接返回,此时并不知道执行的结果/返回值。等其他地方(B)处理请求完成后,把结果主动发过来(A通过回调之类的方法去获取),这个时候A才认为请求执行完成

同步IO/异步IO

异步IO.jpg

异步IO在poxis中的规定: 告诉内核启动某个操作(包括将数据从内核态复制到用户态)完成后通知我们。

需要注意的是同步IO需要进程主动将数据从内核空间拷贝到用户空间,异步则是从内核空间拷贝到用户空间完成后才通知进程。

信号驱动IO就是同步的,因为是内核通知我们何时可以启动IO操作,但IO操作(内核-用户)还未开始

POXIS中的术语:

同步IO操作: 导致请求进程阻塞,直到IO操作完成

异步IO操作: 不导致请求进程阻塞

5种IO的对比

5种IO.jpg


ET触发下,为什么一定要是非阻塞

边缘触发下,用阻塞模型会存在功能上的问题,所以要用非阻塞

当阻塞模式下,recv会一直阻塞接受数据,如果没有一次读取完成所有的数据,ET是边缘触发,只能触发一次epoll_wait更新,剩下的未读取完成的数据就不能继续读入了,除非网络另一端发来新的消息。

同样的,如果一次没有写完,则其他待发送数据,只能等到新的写请求才能触发。所以ET再非阻塞模式下要求循环把数据读取完成。

ET触发下,accept问题

accept事件一次只能从syn就绪队列中取一个放进accept队列,如果同一时刻有多个就绪连接,只accept一次,剩下的连接在下一次epoll_wait也不会触发,LT模式下就没问题

ET模式下,不管阻塞还是非阻塞,都要一次把所有的就绪队列accept成功。可以使用循环。

使用epoll时需要将socket设为非阻塞吗?

ending

图像 006_2.jpg

----------- ending -----------