I/O模型
目前Linux系统中提供了5种IO处理模型
1.阻塞IO
2.非阻塞IO
3.IO多路复用
4.信号驱动IO
5.异步IO
1.阻塞IO
这是最常用的简单的IO模型。阻塞IO意味着当我们发起一次IO操作后一直等待成功或失败之后才返回,在这期间程序不能做其它的事情。阻塞IO操作只能对单个文件描述符进行操作,详见read或write。
同步阻塞IO:
2.非阻塞IO
我们在发起IO时,通过对文件描述符设置O_NONBLOCK flag来指定该文件描述符的IO操作为非阻塞。非阻塞IO通常发生在一个for循环当中,因为每次进行IO操作时要么IO操作成功,要么当IO操作会阻塞时返回错误EWOULDBLOCK/EAGAIN,然后再根据需要进行下一次的for循环操作,这种类似轮询的方式会浪费很多不必要的CPU资源,是一种糟糕的设计。和阻塞IO一样,非阻塞IO也是通过调用read或writewrite来进行操作的,也只能对单个描述符进行操作。
同步非阻塞IO:
3.IO多路复用
IO多路复用在Linux下包括了三种,select、poll、epoll,抽象来看,他们功能是类似的,但具体细节各有不同:首先都会对一组文件描述符进行相关事件的注册,然后阻塞等待某些事件的发生或等待超时。更多细节详见下面的 "具体怎么用"。IO多路复用都可以关注多个文件描述符,但对于这三种机制而言,不同数量级文件描述符对性能的影响是不同的,下面会详细介绍。
同步IO多路复用:
参考我的另一篇文章:
https://www.sidney.wiki/wangluobiancheng/1225
4.信号驱动IO
信号驱动IO是利用信号机制,让内核告知应用程序文件描述符的相关事件。这里有一个信号驱动IO相关的例子。
但信号驱动IO在网络编程的时候通常很少用到,因为在网络环境中,和socket相关的读写事件太多了,比如下面的事件都会导致SIGIO信号的产生:
(1)TCP连接建立
(2)一方断开TCP连接请求
(3)断开TCP连接请求完成
(4)TCP连接半关闭
(5)数据到达TCP socket
(6)数据已经发送出去(如:写buffer有空余空间)
上面所有的这些都会产生SIGIO信号,但我们没办法在SIGIO对应的信号处理函数中区分上述不同的事件,SIGIO只应该在IO事件单一情况下使用,比如说用来监听端口的socket,因为只有客户端发起新连接的时候才会产生SIGIO信号。
半同步信号驱动IO:
5.异步IO
异步IO和信号驱动IO差不多,但它比信号驱动IO可以多做一步:相比信号驱动IO需要在程序中完成数据从用户态到内核态(或反方向)的拷贝,异步IO可以把拷贝这一步也帮我们完成之后才通知应用程序。我们使用 aio_read 来读,aio_write 写。
同步IO vs 异步IO
- 同步IO指的是程序会一直阻塞到IO操作如read、write完成
- 异步IO指的是IO操作不会阻塞当前程序的继续执行
所以根据这个定义,上面1-4这几种的阻塞IO和非阻塞IO都算是同步的IO,因为当文件操作符可用时我们还是需要阻塞的读或写,同理IO多路复用和信号驱动IO也是同步IO,只有异步IO是完全完成了数据的拷贝之后才通知程序进行处理,没有阻塞的数据读写过程。
多路复用一般会使用同步非阻塞IO
具体实现参考
https://www.sidney.wiki/wangluobiancheng/1225
当设置了非阻塞io后,accept和read将不会阻塞。
进程发起IO系统调用后,如果内核缓冲区没有数据,进程返回一个错误而不会被阻塞;
进程发起IO系统调用后,如果内核缓冲区有数据,内核就会把数据返回进程。(这个时候才会阻塞,所以是同步的!!!)
accept():
在non-blocking模式下,如果返回值为-1,且errno == EAGAIN或errno == EWOULDBLOCK表示no connections没有新连接请求;
recv()/recvfrom():
在non-blocking模式下,如果返回值为-1,且errno == EAGAIN表示没有可接受的数据或很在接受尚未完成;
send()/sendto():
在non-blocking模式下,如果返回值为-1,且errno == EAGAIN或errno == EWOULDBLOCK表示没有可发送数据或数据发送正在进行没有完成。
read/write:
在non-blocking模式下,如果返回-1,且errno == EAGAIN表示没有可读写数据或可读写正在进行尚未完成。
connect():
在non-bloking模式下,如果返回-1,且errno = EINPROGRESS表示正在连接。
需扩展如reactor模型(Java中的Selector和Linux中的epoll都是这种模型)等
前两篇文章很有用:
https://zhuanlan.zhihu.com/p/367591714
https://blog.csdn.net/weixin_44545838/article/details/130994305
https://blog.csdn.net/m0_60259116/article/details/134995631
https://cloud.tencent.com/developer/article/2383534
brpc的io文档介绍:
https://github.com/apache/brpc/blob/master/docs/cn/io.md