点击上方“毕来生”,选择“设为星标”
技术好文定时推送!
作者:毕来生
微信:878799579
前言
很多开源框架都是基于Netty去衍生的,如能很好的理解Netty的运作原理,我们对开源框架的源码可以更轻松的掌握以及上手。故写此系列文章。希望本文中的内容可以对你有帮助,如有遇到描述/画图不正确,请参考上方联系方式联系。会第一时间进行更正。
术语科普
1、同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。就是我调用一个功能,该功能没有结束前,我死等结果。
2、异步:当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)
3、阻塞:阻塞调用函数是指调用结果返回之前,当前线程会被挂起,函数只有在得到结果之后才会返回。也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。例如,我们在socket中调用recv函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。
4、非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。通过select或poll或epoll通知调用者。
5、SIGIO:文件描述符准备就绪, 可以开始进行输入/输出操作.
6、recvform:函数原型:ssize_t recvfrom(int sockfd,void *buf,size_t len,unsigned int flags, struct sockaddr *from,socket_t *fromlen); ssize_t 相当于 long int,socket_t 相当于int
7、Sio_read:sio_read返回的是整型值int,>0表示返回成功
8、select:select本质是通过设置或检查存放fd标志位的数据结构来进行下一步处理。
Linux五大IO模型
linux中IO的类型分为四类:同步(sync)和异步(async),阻塞(block)和非阻塞(unblock)
1、阻塞IO模型
进程会一直阻塞,直到数据拷贝完成。模型图如下所示
步骤如下:
1、应用程序调用一个IO函数
2、应用程序阻塞
3、等待数据准备就绪
4、从内核复制到用户空间
5、返回是否成功信息
6、开始处理数据
2、非阻塞IO模型
通过进程反复调用IO函数,在数据拷贝过程中,进程是阻塞的。模型图如下所示
步骤如下:
1、应用程序调用一个IO函数
2、判断内核数据报是否已经准备就绪如准备就绪则看第三点,如准备未就绪则看第四点
3、等待数据准备就绪
4、返回EWOULDBLOCK
5、从内核复制到用户空间
6、返回是否成功信息
7、开始处理数据
3、IO复用模型
主要是select和epoll,对一个IO端口,两次调用,两次返回。模型如下所示
步骤如下:
1、应用程序调用Select
2、检查数据报是否已经准备就绪
3、等待数据准备就绪
4、如数据报已准备好,返回可读取数据
5、应用程序调用Recvform
6、复制数据报
7、从内核复制到用户空间
8、返回是否成功信息
9、开始处理数据
4、信号驱动IO模型
两次调用,再次返回
首先允许套接口进行信号驱动IO,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用IO函数处理数据,模型如下所示
步骤如下:
1、允许套接口进行信号驱动IO
2、建立一个信号处理函数
3、等待数据准备就绪
4、如数据报已准备好,提交到SIGIO信号处理
5、应用程序调用Recvform
6、复制数据报
7、从内核复制到用户空间
8、返回是否成功信息
9、开始处理数据
5、异步IO模型
数据拷贝时进程无阻塞,模型如下所示
步骤如下:
1、应用进程aio_read
2、检查内核数据报是否已经准备就绪,如未准备就绪,返回第一点,如准备就绪则继续向下看第三点
3、等待数据准备就绪
4、如数据报已准备好
6、复制数据报
7、从内核复制到用户空间
8、提交到aio_read
同步 or 异步
1、阻塞I/O (blocking I/O)
2、非阻塞I/O (nonblocking I/O)
3、I/O 复用 (I/O multiplexing)
4、信号驱动I/O (signal driven I/O (SIGIO))
5、异步I/O (asynchronous I/O)
前四种都是同步,只有最后一种才是异步IO