你可以这么理解五种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 ...
随机推荐
- python: 爬取[博海拾贝]图片脚本
练手代码,聊作备忘: # encoding: utf-8 # from __future__ import unicode_literals import urllib import urllib2 ...
- web配置详细解释
<?xml version="1.0"?> <!--注意: 除了手动编辑此文件以外,您还可以使用 Web 管理工具来配置应用程序的设置.可以使用 Visual S ...
- Java反射基础知识
反射机制就是可以把一个类,类的成员(属性.方法)当成一个对象来操作,也就是说,类,类的成员,我们在运行的时候可以动态的去操作它们. 所有的Java类都继承了Object类,在Object类中定义了一个 ...
- abap 常用TCODE
ABAP: 通过查询表TSTC或者TSTCT:SAP系统将所有的事务代码都存储在这个表中,包括字开发的Y*和Z* TCODE 事务代码功能描述 CG3Y 下载服务器上文件 CG3Z upload fi ...
- 位移运算 << >> >>>
位移运算都是补码的运算 左移<<:左移后第一位可能是1,也可能是0,所以可能是正数,也可能是负数,正负都补0 右移>>:抹掉最后一位,近似于十进制值除以2,负数右移高位补1,正 ...
- SpringMVC 使用PUT请求遇到的问题小结
最近在使用REST风格的URL进行CURD操作的学习过程中 发现使用PUT请求时候提交表单进行修改操作 报错:Request method 'PUT' not supported 在网上查找资料发现是 ...
- c++11新标准for循环和lambda表达式
:first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...
- ionic3自定义android原生插件
一.创建一个android项目,编写插件功能,并测试ok,这里以一个简单的调用原生Toast.makeText为例. 1.新建android项目 2.编写插件类 package com.plugin. ...
- java之servlet学习基础(一)
这一阵子在学java三大框架.却在学习过程中发现前面的知识已经忘记了.所以决定写一篇博客来总结回顾之前的学习. 1.Servlet是什么? servlet是一个运行在服务器端的小应用程序.通过HTTP ...
- 刷机魅蓝note2
直接上了. 情况: 魅蓝note2 公共版 忘记flyme 密码,手机号也换了,,找不回了..只能刷了.网上说就算刷了也不行,还是要输入flyme 密码 1. 直接刷官方的zip 包,不行,仍然要输 ...