网络IO模型

这里对网络IO做一次总结

《Unix网络编程》一书中对网络IO模型的总结如下:

  • 同步模型(synchronous I/O)
    • 阻塞I/O(bloking I/O)
    • 非阻塞I/O(non-blocking I/O)
    • 多路复用I/O(multiplexing I/O)
    • 信号驱动式I/O(signal-driven I/O)
  • 异步I/O(asynchronous I/O)

阻塞I/O

阻塞IO是最常用的模式,进程发起recvfrom系统调用后,进程就被阻塞了,然后等待数据准备好,数据从内核态拷贝到用户态后,进程再进行处理。

非阻塞I/O

非阻塞IO正好相反,进程发起recvfrom系统调用后不会阻塞,马上会得到返回结果,如果此时没有数据,会返回EWOULDBLOCK,用户进程可以不断地尝试recefrom,然后有数据处理的时候,函数调用仍然是阻塞的。

多路复用I/O

多路复用有两个系统调用selectpoll,就select函数来说,其可以监听多个文件描述符,当有数据可以处理的时候,系统调用将会返回,然后用户进行可以调用recvfrom进行数据读取。

异步I/O

用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。

同步和异步模型的区别

关于同步和异步,我的理解是数据的获取方式:同步模型,数据是用户态尝试去向内核态获取数据的;异步模型,数据是从内核态拷贝到用户态,并通知用户进程数据ok了。

关于epoll

epoll到底是同步还是异步的呢?
我们知道epoll属于多路复用IO,那么它应该是同步的。但是,epoll因为采用mmap的机制,使得内核socket buffer和用户空间的buffer共享,从而省去了数据拷贝,这也意味着,当epoll回调上层的 callback函数来处理socket数据时,数据已经从内核层“自动“”到了用户空间。
stevens老爷子写《Unix网络编程》已经是上个世纪的事情了,当时epoll还没有,我觉得epoll不属于任何一种吧。