你可以这么理解五种I/O模型
因为项目需要,接触和使用了Netty,Netty是高性能NIO通信框架,在业界拥有很好的口碑,但知其然不知其所以然。
所以本系列文章将从基础开始学起,深入细致的学习NIO。本文主要是介绍五种I/O模型,概念是枯燥的,不过还是得理解才行。
LINUX与UNIX中一些概念
在网络管理,Linux UNIX很相似.UNIX系统一直被用做高端应用或服务器系统,因此拥有一套完善的网络管理机制和规则, Linux沿用了这些出色的规则,使网络的可配置能力很强,为系统管理提供了极大的灵活性.
通俗一点讲,就是在网络方面Linux和UNIX是非常相似的,网络模型大可借鉴UNIX网络编程中的描述。
这里介绍四个概念,方便五种I/O模型的理解:
1.所有外部设备皆文件
Linux的内核将所有的外部设备都看作是一个文件来操作,对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符)。
面对一个socket也会有相应的描述符,成为socketfd(socket描述符),描述符就是一个数字,他指向内核中的一个结构体(文件路径,数据区等一些属性)。
2.recvfrom()函数
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, strut sockaddr *from, socklen_t *addrlen);
该函数执行成功,则返回读或写的字节数,如出错则为-1。
*from参数,指向一个将由该函数在返回时填写数据包发送者的协议地址的套接字地址结构,
*addrlen参数,套接字地址结构,并且该结构体中填写的则放在addrlen所指的整数中返回给调用者
通过这两个参数,我们可以知道是谁发送了数据包(udp情况下),或是谁发送了数据包(TCP情况下);
3.应用进程与内核
应用进程就是常规的程序,用户程序,打开任务管理器,在应用分组就可以看到应用进程,如下图所示:

图中红框内的,都是应用进程。所有的应用进程都是运行在用户态中。(用户态的概念直接戳链接),运行时所处空间是用户空间
内核就是操作系统的内核,它的作用是将应用进程与硬件分开。可以这么理解,所有涉及到I/O的操作都直接或者间接的经过内核程序。
如果应用进程可以直接操作硬件,那么一些病毒就会蓄意的对计算机硬件进行破坏,那就不可控制了。这样的机制就保证了系统的安全性。运行时是处于内核态,所处空间是内核空间。
网络传输数据,首先是内核先接收到数据,然后内核将数据拷贝到用户态中供应用进程使用。
请先理解上面的基本概念,接下来将介绍五种传统的I/O模型。
同步阻塞I/O
最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。
在应用进程通过内核调用recvfrom()函数,其系统调用直到数据包到达且被复制到应用进程的缓冲区或者发生错误时才会返回,在此期间会一直等待。
这句话太晦涩难懂了,简单点说就是:应用进程通过内核调用recvfrom(),收到数据的话则将数据从内核态复制到用户态,没有收到就一直阻塞。

同步非阻塞I/O
应用系统还是调用recvfrom,但是他不会阻塞与此,而是不断的去轮询的是否有数据准备好,如果没有准备好,就直接返回一个EWOULDBLOCK错误。
总结:
与同步阻塞I/O相比,如果数据准备好,不会一直阻塞与此,而是直接返回错误,接收到错误之后,就可以干点别的事,这是他的优点。但是缺点也很明显,
任务完成的响应延迟增大了。因为很可能在两次轮询之间,socketfd就处于read状态了,所以导致整体的吞吐量下降了。
I/O复用
I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程。
与同步非阻塞I/O不断轮询不同的是,I/O复用是使用一个线程循环轮询socketfd集合是否处于read状态。
Linux提供select/epoll,进程通过一个或者多个socketfd传递给select或poll系统调用,阻塞在select上,这样select/poll可以侦测到多个socketfd是否处于就绪状态。
select/poll是顺序扫描socketfd是否就绪,而且支持的fd很有限。
Linux还提供了一个epoll系统调用,epoll基于事件驱动方式代替顺序扫描,因此性能更高。当有fd就绪时,立即回调函数rollback。
关于select/poll,epoll
select/poll
该函数允许进程指示内核等待多个事件中的任何事件发生,并且只在有一个或多个事件发生或经历一段时间指定的时间才唤醒它。
举个例子,也就是说进程可以通知内核在socketfd集合{1,2,3}进行侦听,知道socketfd集合中任何一个可读的话,就返回。这个等待的过程是阻塞的,它可以侦听多个,但是侦听的数量是有限的。
看下官方关于epoll的解释
The epoll API performs a similar task to poll: monitoring multiple file descriptors to see if I/O is possible on any of them.
The epoll API can be used either as an edge-triggered or a level-triggered interface and scales well to large numbers of watched file descriptors.
epoll和poll执行类似的任务,监控多个fd,如果多个fd中任何一个有I/O时间,即可及时发现。epoll的API既可以作为边触发,也可以作为水平触发接口和可扩展到大量的监视fd。
epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量连接中只有少量活跃的情况下的系统CPU利用率.
epoll与select/poll的对比
一个进程能够打开socketfd的限制
select一个进程能够打开的FD是由FD_SETSIZE限制的,默认是2048,可以选择修改宏然后重新编译服务器代码,相关资料表明这样会带来网络效率的下降。
epoll没有打开FD数量的限制,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max查看,一般来说这个数目和系统内存关系很大。
IO效率不会因为socketfd数量提高而线性下降
select和poll拥有一个很大的socketfd集合和,由于每次都会调用线性扫描全部的集合,带来的后果就是效率线性下降
epoll有着相对更好的解决方案,在很大的socketfd集合中,它只会对活跃的socketfd进行操作。epoll是根据每个fd上面的callback函数实现的,只有活跃的socketfd才会去调用callback函数
mmap加速内核与用户空间的传递
无论是select/poll和epoll,都是需要通过内核将FD消息拷贝到用户空间,拷贝是费时的。epoll通过内核与用户控件mmap同一块内存实现不必要的拷贝,从而加快效率。
总结:
进程通过调用内核中的select/poll/epoll,监听socketfd集合的读写就绪状态,多个socketfd都能在一个线程中交替完成,所谓的复用就是指使用的同一个线程。
I/O复用实际还是同步I/O,归根到底还是应用进程主动向内核查询状态。
I/O多路复用是OS提供的最稳定的IO模型,大部分主流的应用都是基于此种IO模型构建的,比如NodeJS,Netty框架。

信号驱动I/O
首先开启套接字信号驱动I/O功能,并通过系统调用sigaction执行一个信号处理函数,此时系统继续运行,并不会阻塞。
当数据准备就绪时,就为该进程生成一个SIGIO信号,通过信号回调通知,通知应用进程调用recvfrom来读取数据。

异步非阻塞I/O
一句话简单说:产品经理让你改一个需求,并且让你改好了告诉他,给他看一下,于是你就吭哧吭哧的做了,(产品经理就去忙别的事情了,比如又去改需求了)并且做好了叫了产品经理来看。
用户进程进行aio_read系统调用之后,就去干别的事情了。当socketfd数据准备好之后,内核直接复制数据到用户空间,然后内核向用户进程发送通知,数据准备好了。
总结:
整个I/O过程都是非阻塞的,这个是真正的异步非阻塞。

总结:
理解五种I/O模型,有助于理解网络I/O,写出更健壮的代码。
在实际工程项目中,普遍使用I/O复用模型,本章重点介绍了I/O复用模型,Java中的NIO也是基于此。学习I/O模型有助于更好的理解NIO,学习Netty框架。
勿在浮沙筑高楼
参考:
《UNIX网络编程》
《Netty权威指南》
你可以这么理解五种I/O模型的更多相关文章
- I/O模型之一:Unix的五种I/O模型
目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...
- 第3章 文件I/O(5)_五种I/O模型
6. I/O处理方式(5种I/O模型) 6.1 几个概念的辨析 (1)同步和异步 ①是访问数据的方式,主要是针对IO(资源.数据)而言的.关键在于I/O操作完成后,有没有提供通知机制. ②同步的IO, ...
- 五种典型开发周期模型(瀑布、V、原型化、螺旋、迭代)
五种典型开发周期模型(瀑布.V.原型化.螺旋.迭代) 总结一下经常可以见到的系统开发周期模型. 在过去的几年里,可以很奇葩的碰到类似于“创业项目库”这种需求非常明确,工作量十分可控,对质量要求比 ...
- Linux五种I/O模型性能分析
转载自:http://blog.csdn.net/jay900323/article/details/18141217/ socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理 ...
- 转:Windows Socket五种I/O模型
原文转自: Windows Socket五种I/O模型 Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模 ...
- Windows Socket五种I/O模型
转载:http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813637.html 如果你想在Windows平台上构建服务器应用,那么I/O模 ...
- []转帖] 浅谈Linux下的五种I/O模型
浅谈Linux下的五种I/O模型 https://www.cnblogs.com/chy2055/p/5220793.html 一.关于I/O模型的引出 我们都知道,为了OS的安全性等的考虑,进程是 ...
- Unix网络编程中的五种I/O模型_转
转自:Unix网络编程中的的五种I/O模型 下面主要是把unp第六章介绍的五种I/O模型. 1. 阻塞I/O模型 例如UDP函数recvfrom的内核到应用层.应用层到内核的调用过程是这样的:首先把描 ...
- Unix下 五种 I/O模型
Unix下共有五种I/O模型: 1. 阻塞式I/O 2. 非阻塞式I/O 3. I/O复用(select和poll) 4. 信号驱动式I/O(SIGIO) 5. 异步I/O(POSIX的aio ...
随机推荐
- Kubernetes节点维护
1.设置节点为不可调度 kubectl cordon $NODENAME 2.使用kubectl drain优雅的结束节点上的所有 pod 并同时标记节点为不可调度 kubectl drain $NO ...
- 使用react-handsontable
新建一个项目 create-react-app myProject cd myProject npm install handsontable 或者 npm install handsontable- ...
- C#使用反射获取对象变化的情况
记录日志时, 经常需要描述对象的状态发生了怎样的变化, 以前处理的非常简单粗暴: a. 重写class的ToString()方法, 将重要的属性都输出来 b. 记录日志时: 谁谁谁 由 变更前实 ...
- jmeter用Windows电脑分布式部署
当然,java环境.jmeter安装我这里就不说了. 使用1个controller(imac电脑),2个agent(Windows7 系统) 一.agent配置(Windows7系统) 1.电脑环境变 ...
- STS中db.properties配置文件
db.name=root db.password=root db.url=jdbc:mysql://localhost:3306/day13?useUnicode=true&character ...
- 第二阶段第十次spring会议
昨天我对宠物信息进行了添加和调整. 今天我将继续对宠物信息添加保存按钮. private void button2_Click(object sender, EventArgs e) { Settin ...
- JS獲取URL的參數
function GetQueryString(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*) ...
- 【转】异步编程 In .NET
概述 在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们 ...
- SQL语句操作数据
--切换数据库:手动切换和命令切换 use MySchool --向Student表中插入数据 --语法:INSERT [INTO] 表名 (列名) VALUES (值列表) --注意事项: --1. ...
- 根据缺少的so,安装相关的软件
http://blog.csdn.net/dianyueneo/article/details/8161350. ubuntu缺少libGL.so sudo apt-get install apt-f ...