查看“关于:5种I/O模型”的源代码
←
关于:5种I/O模型
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Linux]] [[category:Java]] == 关于 == 【'''讨论的背景是 Unix/Linux 环境下的 network IO'''】 I/O(Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作。 * I/O有:内存I/O、网络I/O 和 磁盘I/O 三种。(通常说的I/O指的是后两者) LINUX 中进程无法直接操作 I/O 设备,其必须通过系统调用请求 '''kernel''' 来协助完成 I/O 动作;内核会为每个 I/O 设备维护一个'''缓冲区'''。 : 对于一个输入操作来说,进程I/O系统调用后,内核会先看缓冲区中有没有相应的缓存数据,没有的话再到设备中读取,因为设备I/O一般速度较慢,需要等待;内核缓冲区有数据则直接复制到进程空间。 所以,对于一个 network I/O,它会涉及到两个系统对象:'''调用I/O的process'''(or thread),'''系统内核'''(kernel)。 当一个 I/O 操作发生时,'''kernel 中会经历两个阶段:''' # '''等待数据准备'''(Waiting for the data to be ready); # '''将数据从内核拷贝到进程中'''(Copying the data from the kernel to the process); 记住这两点很重要,因为这些 IO Model 的区别就是在两个阶段上各有不同的情况。 == 5种I/O模型 == 《UNIX网络编程》:5 种I/O模型分别是'''阻塞I/O模型'''、'''非阻塞I/O模型'''、'''I/O复用模型'''、'''信号驱动的I/O模型'''、'''异步I/O模型'''; * 其中,前 4 种为“同步I/O操作”,只有 异步I/O模型 是“异步I/O操作”。 === 阻塞I/O模型(blocking IO) === ---- '''进程阻塞于 recvfrom 调用,直到返回成功指示'''。(进程阻塞直到 kernel 中两个阶段结束) : [[File:5种IO模型:阻塞IO模型.png|600px]] 典型应用: * 阻塞socket;【默认情况下所有的 socket 都是 blocking】 * '''Java BI/O'''; 特点: * '''进程阻塞挂起不消耗CPU资源,及时响应每个操作'''; * 实现难度低、开发应用较容易; * 适用并发量小的网络应用开发; * '''不适用并发量大的应用''':因为一个请求I/O会阻塞进程,所以,得为每请求分配一个处理进程(线程)以及时响应,系统开销大。 === 非阻塞I/O模型(nonblocking IO) === ---- '''进程反复调用 recvfrom,并等待返回成功指示'''。(进程反复调用 recvfrom 而不阻塞) : [[File:5种IO模型:非阻塞IO模型.png|600px]] 进程发起 I/O 系统调用后: # 如果内核缓冲区没有数据,需要到 I/O 设备中读取,'''进程返回一个错误而不会被阻塞'''; # 如果内核缓冲区有数据,内核就会把数据返回进程。 典型应用: * socket(linux下,可以通过设置socket使其变为non-blocking) 特点: * '''进程轮询(重复)调用,消耗CPU的资源'''; * 实现难度低、开发应用相对阻塞I/O模式较难; * 适用并发量较小、且不需要及时响应的网络应用开发; === I/O复用模型(IO multiplexing) === ---- I/O复用模型(也称:“event driven IO”,事件驱动I/O),其好处就在于'''单个process就可以同时处理多个网络连接的 IO'''。 : [[File:5种IO模型:IO复用模型.png|600px]] 基本原理:【select/epoll 这个 function 会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程】 <pre> 等待数据准备: 用户进程调用 select,整个进程被block。 同时,kernel 会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。 将数据从内核拷贝到进程中: 用户进程再调用 recvfrom(read 操作),将数据从kernel拷贝到用户进程。 </pre> * '''使用到两个系统调用''':(select 和 recvfrom) *# select:轮询socket,等待数据; *# recvfrom:将数据从内核拷贝到进程中; * '''用户进程阻塞两次''': *# 进程阻塞于 select 调用,等待某个socket可读;('''阻塞于 select 调用''') *# 进程阻塞于 数据拷贝到应用缓冲区;('''阻塞于 recvfrom 调用''') 注意: * 其优势,并不在于性能(连接数不高时,并不一定比“阻塞I/O”更好),而是在于同时处理多个connection; 典型应用: * select、poll、epoll三种多路I/O复用方案;(nginx都可以选择使用这三个方案) * '''Java NIO'''; 特点: * '''专一进程解决多个进程I/O的阻塞问题''',性能好;'''Reactor模式'''; * 实现、开发应用难度较大; * '''适用高并发服务应用开发''':一个进程(线程)响应多个请求; ==== select、poll、epoll ==== Linux 中I/O复用的实现方式主要有: # '''select''':注册I/O、阻塞扫描。 #* 监听的 I/O 最大连接数不能多于 '''FD_SIZE'''; # '''poll''':原理和 select 相似,'''没有数量限制''',但I/O数量大扫描线性性能下降; # '''epoll''' :事件驱动不阻塞,'''mmap''' 实现内核与用户空间的消息传递,数量很大。 #* Linux 2.6 后内核支持; #*【Redis 的单线程模型中,“文件事件处理器”就采用 epoll 实现 多路I/O复用】 === 信号驱动的I/O模型(signal driven IO) === ---- 当进程发起一个 I/O 操作,会向内核注册一个'''信号处理函数''',然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用 I/O 读取数据。 * 进程阻塞在第二个阶段(数据拷贝到应用缓冲区期间); : [[File:5种IO模型:信号驱动IO模型.png|600px]] 典型应用: *【好像应用比较少】 特点: * 回调机制,实现、开发应用难度大; === 异步I/O模型(asynchronous IO) === ---- 用户线程与内核异步执行: * 用户线程:发起一个 aio_read 后(立刻得到内核返回),继续执行其他逻辑; * 内核: *# 收到一个 aio_read 后立刻返回。 *# 然后,两个阶段(等待数据准备完成,将数据拷贝到用户内存)完成之后,给用户进程发送一个 signal。 : [[File:5种IO模型:异步IO模型.png|600px]] 典型应用: * '''JAVA7 AIO''';【???】 * 高性能服务器应用; 特点: * 不阻塞,数据一步到位;'''Proactor模式'''; * 需要操作系统的底层支持,LINUX 2.5 版本内核首现,2.6 版本产品的内核标准特性; * 实现、开发应用难度大; * '''非常适合高性能高并发应用'''; == I/O模型比较 == : [[File:5种IO模型比较.png|600px]] == I/O:blocking vs non-blocking、synchronous vs asynchronous == === blocking vs non-blocking === blocking:用户进程会阻塞直到整个 I/O 结束;(阻塞I/O模型) non-blocking:在kernel还准备数据的情况下会立刻返回;(非阻塞I/O模型) * 但,阻塞I/O模型、I/O复用模型、信号驱动的I/O模型,都存在用户线程阻塞的情况。 === synchronous vs asynchronous === 对于 synchronous IO 和 asynchronous IO,Stevens给出的定义(其实是POSIX的定义)如下: <pre> A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes; An asynchronous I/O operation does not cause the requesting process to be blocked; </pre> * 此处,“I/O operation”是指真实的IO操作,就是例子中的recvfrom这个system call。 对于“非阻塞I/O模型”(non-blocking IO):在执行 recvfrom 这个system call的时候,如果 kernel 的数据没有准备好,这时候不会block进程。但是,当kernel中数据准备好的时候,recvfrom 会将数据从kernel拷贝到用户内存中,这个时候进程是被block了,在这段时间内,进程是被block的。【见上一节:“I/O模型比较”图】 抛却以上说法,其实,二者重点关注在“用户线程发送I/O之后,是否关注内核操作”,以此作为区分: : '''只有“异步I/O模型”是异步I/O''',其余'''“阻塞I/O模型”、“非阻塞I/O模型”、“I/O复用模型”、“信号驱动的I/O模型”都属于同步I/O'''。
返回至“
关于:5种I/O模型
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息