<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.eijux.com/index.php?action=history&amp;feed=atom&amp;title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI%2FO%E6%A8%A1%E5%9E%8B</id>
	<title>关于：5种I/O模型 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.eijux.com/index.php?action=history&amp;feed=atom&amp;title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI%2FO%E6%A8%A1%E5%9E%8B"/>
	<link rel="alternate" type="text/html" href="http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;action=history"/>
	<updated>2026-04-25T15:33:13Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.38.2</generator>
	<entry>
		<id>http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;diff=4979&amp;oldid=prev</id>
		<title>2021年11月25日 (四) 14:53 Eijux</title>
		<link rel="alternate" type="text/html" href="http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;diff=4979&amp;oldid=prev"/>
		<updated>2021-11-25T14:53:42Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;zh-Hans-CN&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;←上一版本&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2021年11月25日 (四) 22:53的版本&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;第1行：&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第1行：&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[category:Linux]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[category:Linux]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[category:Java]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== 关于 ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== 关于 ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;【'''讨论的背景是 Unix/Linux 环境下的 network IO'''】&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/ins&gt;【'''讨论的背景是 Unix/Linux 环境下的 network IO'''】&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;I/O（Input/Output，输入/输出）即数据的读取（接收）或写入（发送）操作。&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;I/O（Input/Output，输入/输出）即数据的读取（接收）或写入（发送）操作。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Eijux</name></author>
	</entry>
	<entry>
		<id>http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;diff=3214&amp;oldid=prev</id>
		<title>Eijux：​/* 关于 */</title>
		<link rel="alternate" type="text/html" href="http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;diff=3214&amp;oldid=prev"/>
		<updated>2021-05-12T19:07:31Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;关于&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;zh-Hans-CN&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;←上一版本&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2021年5月13日 (四) 03:07的版本&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l2&quot;&gt;第2行：&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第2行：&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== 关于 ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== 关于 ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;【讨论的背景是 &lt;/del&gt;Linux 环境下的 network &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;IO】&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;【'''讨论的背景是 Unix/&lt;/ins&gt;Linux 环境下的 network &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;IO'''】&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;I/O（Input/Output，输入/输出）即数据的读取（接收）或写入（发送）操作。&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;I/O（Input/Output，输入/输出）即数据的读取（接收）或写入（发送）操作。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Eijux</name></author>
	</entry>
	<entry>
		<id>http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;diff=3211&amp;oldid=prev</id>
		<title>Eijux：​建立内容为“category:Linux  == 关于 == 【讨论的背景是 Linux 环境下的 network IO】  I/O（Input/Output，输入/输出）即数据的读取（接收）或写…”的新页面</title>
		<link rel="alternate" type="text/html" href="http://wiki.eijux.com/index.php?title=%E5%85%B3%E4%BA%8E%EF%BC%9A5%E7%A7%8DI/O%E6%A8%A1%E5%9E%8B&amp;diff=3211&amp;oldid=prev"/>
		<updated>2021-05-12T18:50:27Z</updated>

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