异步通信在⽣活中的例⼦_5种IO模型、阻塞IO和⾮阻塞IO、
同步IO和异步IO
5种IO模型、阻塞IO和⾮阻塞IO、同步IO和异步IO
看了⼀些⽂章,发现有很多不同的理解,可能是因为⼤家⼊切的⾓度、环境不⼀样。所以,我们先说明基本的IO操作及环境。本⽂是在《UNIX⽹络编程 卷1:套接字联⽹API》6.2节"I/O 模型 "的基础上,即UNIX/LINUX环境下的⽹络 IO环境下的理解,它⾥⾯给出的例⼦是读取(接收)⽹络UDP数据。下⾯简单写写⾃⼰对这些IO模型的理解。
1、IO
IO (Input/Output,输⼊/输出)即数据的读取(接收)或写⼊(发送)操作,通常⽤户进程中的⼀个完整IO分为两阶段:⽤户进程空间<-->内核空间、内核空间<-->设备空间(磁盘、⽹络等)。IO有内存IO、⽹络IO和磁盘IO三种,通常我们说的IO指的是后两者。
LINUX中进程⽆法直接操作I/O设备,其必须通过系统调⽤请求kernel来协助完成I/O动作;内核会为每个I/O设备维护⼀个缓冲区。
对于⼀个输⼊操作来说,进程IO系统调⽤后,内核会先看缓冲区中有没有相应的缓存数据,没有的话再到设备中读取,因为设备IO⼀般速度较慢,需要等待;内核缓冲区有数据则直接复制到进程空间。
所以,对于⼀个⽹络输⼊操作通常包括两个不同阶段:
(1)等待⽹络数据到达⽹卡→读取到内核缓冲区,数据准备好;
(2)从内核缓冲区复制数据到进程空间。
2、5种IO模型
《UNIX⽹络编程》说得很清楚,5种IO模型分别是阻塞IO模型、⾮阻塞IO模型、IO复⽤模型、信号驱动的IO模型、异步IO模型;前4种为同步IO操作,只有异步IO模型是异步IO操作。下⾯这样些图,是它⾥⾯给出的例⼦:接收⽹络UDP数据的流程在IO模型下的分析,在它的基础上再加以简单描述,以区分这些IO模型。
2-1、阻塞IO模型
进程发起IO系统调⽤后,进程被阻塞,转到内核空间处理,整个IO处理完毕后返回进程。操作成功则进程获取到数据。
1、典型应⽤:阻塞socket、Java BIO;
2、特点:
进程阻塞挂起不消耗CPU资源,及时响应每个操作;
实现难度低、开发应⽤较容易;
适⽤并发量⼩的⽹络应⽤开发;
不适⽤并发量⼤的应⽤:因为⼀个请求IO会阻塞进程,所以,得为每请求分配⼀个处理进程(线程)以及时响应,系统开销⼤。
2-2、⾮阻塞IO模型
进程发起IO系统调⽤后,如果内核缓冲区没有数据,需要到IO设备中读取,进程返回⼀个错误⽽不会被阻塞;进程发起IO系统调⽤后,如果内核缓冲区有数据,内核就会把数据返回进程。
对于上⾯的阻塞IO模型来说,内核数据没准备好需要进程阻塞的时候,就返回⼀个错误,以使得进程不被阻塞。
1、典型应⽤:socket是⾮阻塞的⽅式(设置为NONBLOCK)
2、特点:
进程轮询(重复)调⽤,消耗CPU的资源;
实现难度低、开发应⽤相对阻塞IO模式较难;
适⽤并发量较⼩、且不需要及时响应的⽹络应⽤开发;
2-3、IO复⽤模型
多个的进程的IO可以注册到⼀个复⽤器(select)上,然后⽤⼀个进程调⽤该select, select会监听所有注册进来的IO;
如果select没有监听的IO在内核缓冲区都没有可读数据,select调⽤进程会被阻塞;⽽当任⼀IO在内核缓冲区中有可数据时,select调⽤就会返回;
⽽后select调⽤进程可以⾃⼰或通知另外的进程(注册进程)来再次发起读取IO,读取内核中准备好的数据。
可以看到,多个进程注册IO后,只有另⼀个select调⽤进程被阻塞。
1、典型应⽤:select、poll、epoll三种⽅案,nginx都可以选择使⽤这三个⽅案;Java NIO;
2、特点:
专⼀进程解决多个进程IO的阻塞问题,性能好;Reactor模式;
实现、开发应⽤难度较⼤;
适⽤⾼并发服务应⽤开发:⼀个进程(线程)响应多个请求;
3、select、poll、epoll
Linux中IO复⽤的实现⽅式主要有select、poll和epoll:
Select:注册IO、阻塞扫描,监听的IO最⼤连接数不能多于FD_SIZE;
Poll:原理和Select相似,没有数量限制,但IO数量⼤扫描线性性能下降;
Epoll :事件驱动不阻塞,mmap实现内核与⽤户空间的消息传递,数量很⼤,Linux2.6后内核⽀持;
2-4、信号驱动IO模型
当进程发起⼀个IO操作,会向内核注册⼀个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送⼀个信号给进程,进程便在信号处理函数中调⽤IO读取数据。
1、特点:回调机制,实现、开发应⽤难度⼤;
2-5、异步IO模型
当进程发起⼀个IO操作,进程返回(不阻塞),但也不能返回果结;内核把整个IO处理完后,会通知进程结果。如果IO操作成功则进程直接获取到数据。
1、典型应⽤:JAVA7 AIO、⾼性能服务器应⽤
2、特点:
不阻塞,数据⼀步到位;Proactor模式;
需要操作系统的底层⽀持,LINUX 2.5 版本内核⾸现,2.6 版本产品的内核标准特性;
实现、开发应⽤难度⼤;
⾮常适合⾼性能⾼并发应⽤;
3、IO模型⽐较
3-1、阻塞IO调⽤和⾮阻塞IO调⽤、阻塞IO模型和⾮阻塞IO模型
进程通信方式注意这⾥的阻塞IO调⽤和⾮阻塞IO调⽤不是指阻塞IO模型和⾮阻塞IO模型:
阻塞IO调⽤ :在⽤户进程(线程)中调⽤执⾏的时候,进程会等待该IO操作,⽽使得其他操作⽆法执⾏。
⾮阻塞IO调⽤:在⽤户进程中调⽤执⾏的时候,⽆论成功与否,该IO操作会⽴即返回,之后进程可以进⾏其他操作(当然如果是读取到数据,⼀般就接着进⾏数据处理)。
这个直接理解就好,进程(线程)IO调⽤会不会阻塞进程⾃⼰。所以这⾥两个概念是相对调⽤进程本⾝状态来讲的。
从上⾯对⽐图⽚来说,阻塞IO模型是⼀个阻塞IO调⽤,⽽⾮阻塞IO模型是多个⾮阻塞IO调⽤+⼀个阻塞IO调⽤,因为多个IO检查会⽴即返回错误,不会阻塞进程。
⽽上⾯也说过了,⾮阻塞IO模型对于阻塞IO模型来说区别就是,内核数据没准备好需要进程阻塞的时候,就返回⼀个错误,以使得进程不被阻塞。
3-2、同步IO和异步IO
同步IO:导致请求进程阻塞,直到I/O操作完成。
异步IO:不导致请求进程阻塞。
上⾯两个定义是《UNIX⽹络编程 卷1:套接字联⽹API》给出的。这不是很好理解,我们来扩展⼀下,先说说同步和异步,同步和异步关注的是双⽅的消息通信机制:
同步:双⽅的动作是经过双⽅协调的,步调⼀致的。
异步:双⽅并不需要协调,都可以随意进⾏各⾃的操作。
这⾥我们的双⽅是指,⽤户进程和IO设备;明确同步和异步之后,我们在上⾯⽹络输⼊操作例⼦的基础上,进⾏扩展定义:
同步IO:⽤户进程发出IO调⽤,去获取IO设备数据,双⽅的数据要经过内核缓冲区同步,完全准备好后,再复制返回到⽤户进程。⽽复制返回到⽤户进程会导致请求进程阻塞,直到I/O操作完成。
异步IO:⽤户进程发出IO调⽤,去获取IO设备数据,并不需要同步,内核直接复制到进程,整个过程不导致请求进程阻塞。
所以, 阻塞IO模型、⾮阻塞IO模型、IO复⽤模型、信号驱动的IO模型者为同步IO模型,只有异步IO模型是异步IO。
---------------------
作者:尐譽
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论