你可以这么理解五种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 ...
随机推荐
- P1579哥德巴赫猜想
写来自己学习用~ 题目内容: 1742年6月7日哥德巴赫写信给当时的大数学家欧拉,正式提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和.质数是指除了1和本身之外没有其他约数的数,如2和1 ...
- Scrapy中集成selenium
面对众多动态网站比如说淘宝等,一般情况下用selenium最好 那么如何集成selenium到scrapy中呢? 因为每一次request的请求都要经过中间件,所以写在中间件中最为合适 from se ...
- Spring常用注解总结(3)
@Configuration 表示该类为"配置类",可替换xml配置文件.与@Component不同的是,@Configuration会生成CGLIB代理class. @Targe ...
- 从本地上传项目到 github 以及从github 下载项目到本地环境
前置条件:成功安装github,安装成功后,要配置密钥,不然上传不成功,要报错 具体上传步骤: git init //初始化 git add 文件名 //更新文件 git commit -m ...
- Numpy 线性代数
Numpy 提供了线性代数库 linalg , 该库包含了线性代数所需的所有功能,可以看卡下面的说明: 函数 描述 dot 两个数组的点积, 即元素对应相乘 vdot 两个向量的点积 inner 两个 ...
- vue中提示$index is not defined
今天学习Vue中遇到了一个报错信息:$index is not defined,是我写了个for循环在HTML中,然后是因为版本的问题 下面是解决方法: 原来的是 v-for="person ...
- 用STS构建spring boot
操作步骤:1. 登录地址http://spring.io/tools 下载sts,spring-tool-suite-3.9.5.RELEASE-e4.8.0-win32-x86_64.zip2. 解 ...
- Python从入门到精通之Second!
初识Python基础! -基础 -扩展名可以是任意的,但是导入模块时,如果不是.py文件就会报错. -两种执行方式 1.python解释器 文件名.py 文件路径 -Li ...
- centos 6.5升级openssl
1.下载升级版本 wget https://www.openssl.org/source/openssl-1.1.0i.tar.gz 2.安装 zlib zlib-devel yum -y insta ...
- JAVA 8 主要新特性 ----------------(七)新时间日期 API -----LocalDateTime
一.LocalDateTime简介 二.实战讲解 LocalDateTime localDateMax = LocalDateTime.MAX; System.out.println("lo ...