硬核图解网络IO模型!
硬核图解网络IO模型!
月伴飞鱼同步阻塞
用户空间的应用程序执行一个系统调用,这会导致应用程序阻塞,直到数据准备好,并且将数据从内核复制到用户进程。
最后进程再处理数据,在等待数据到处理数据的两个阶段,整个进程都被阻塞,不能处理别的网络IO。
同步非阻塞
非阻塞的系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。
进程在返回之后,可以干点别的事情,然后再发起系统调用。
重复上面的过程,循环往复的进行系统调用,这个过程通常被称之为轮询。
轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理。
需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态。
IO多路复用
IO多路复用,这是一种进程预先告知内核的能力,让内核发现进程指定的一个或多个IO条件就绪了,就通知进程。
IO复用的实现方式目前主要有Select、Poll和Epoll。
信号驱动
首先允许Socket进行信号驱动IO,并安装一个信号处理函数,进程继续运行并不阻塞。
当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。
此种IO方式存在的一个很大的问题:
- Linux中信号队列是有限制的,如果超过这个数字问题就无法读取数据。
异步非阻塞
当用户线程进行了系统调用,立刻就可以开始去做其它的事,用户线程不阻塞。
- 准备数据:当内核一直等到数据准备好了,它就会将数据从内核内核缓冲区,拷贝到用户缓冲区。
- 内核会给用户线程发送一个信号,或者回调用户线程注册的回调接口,告诉用户线程操作完成了。
- 用户线程读取用户缓冲区的数据,完成后续的业务操作。
信号驱动IO,异步IO的主要区别在于:
- 信号驱动由内核告诉我们何时可以开始一个IO操作(数据在内核缓冲区中)。
- 而异步IO则由内核通知IO操作何时已经完成(数据已经在用户空间中)。
BIO,NIO,AIO的区别:
BIO:
- 同步并阻塞,服务实现模式为一个连接对应一个线程,即客户端发送一个连接,服务端要有一个线程来处理。
- 如果连接多了,线程数量不够,就只能等待,即会发生阻塞。
- 适用连接数目比较小且固定的架构。
NIO:
- 同步非阻塞,服务实现模式是一个线程可以处理多个连接,即客户端发送的连接都会注册到多路复用器上。
- 然后进行轮询连接,有I/O请求就处理。
- 适用连接数目多且连接比较短的架构,如:聊天服务器,弹幕系统等,编程比较复杂。
AIO:
- 异步非阻塞,引入了异步通道,采用的是Proactor模式。
- 适用连接数目多且连接长的架构,如相册服务器。