从 Linux 操作系统谈谈 IO 模型(终)
Linux 为什么要区分内核空间与用户空间?
Linux 操作系统的 IO 模型有哪几种?有啥区别?
常说的阻塞现象,到底是咋回事?
网络编程研发时,那块到底耗时最多,代码是否还有优化空间?
前几期的分享,我们站在编码视角去聊 Java IO,旨在理解与编码,本次从 Linux 操作系统层面了解一下 IO 模型,这样方能做到知其然,知其所以然。
01. 内核空间、用户空间
万事万物我们看到的皆是表象,操作系统也不例外。我们经常打交道的用户界面,是操作系统的外在表象,内核才是操作系统的内在核心。
内核,可以访问受保护的内存空间,拥有访问底层硬件设备的所有权限(比如读写磁盘文件,分配回收内存,从网络接口读写数据等等)。
为了内核的安全,操作系统将虚拟空间划分为内核空间(内核代码运行的地方)和用户空间(用户程序代码运行的地方)。内核空间和用户空间是隔离的,这样即使用户的程序崩溃了,内核也不受影响。
另外,用户程序不能直接操作内核,需要通过系统调用来与内核进行通信(应用程序通过内核提供的接口来完成访问)。
02. Socket 通信流程
Socket 通信流程应该不再陌生,本次分享着重剖析图中圈住的部分。
站在服务端的视角,对于一次 Socket 的数据读取操作流程,如图示意,网络数据到达网卡,数据先被拷贝到内核缓冲区中,然后从内核缓冲区拷贝到进程用户空间。
站在服务端的视角,当一个读操作发生时,稍微再细化一下,其实会经历两个阶段。
第一阶段:等待数据准备。
例如:recv() 等待数据,需要等待网络上的数据分组到达,然后被复制到内核的缓冲区。
第二阶段:将数据从内核缓冲区拷贝到用户空间。
例如:recv() 接收连接发送的数据后,需要把数据复制到内核缓冲区,再从内核缓冲区复制到进程用户空间。
一定记住这两个阶段,也正因为存在这两个阶段,Linux系统升级迭代中出现了五种网络 IO 模型。
03. Linux 网络 IO 模型
(一)阻塞 IO 模型 - Blocking IO
图解:当应用进程调用了 recv() 这个系统调用,内核就开始了 IO 的第一个阶段:准备数据。这个过程需要等待,也就是说数据被拷贝到操作系统内核的缓冲区中是需要一个过程的。而在用户进程这边,整个进程会被阻塞。当内核一直等到数据准备好了,它就会将数据从内核中拷贝到用户内存,然后内核返回结果,用户进程才解除阻塞的状态。
特点:在 IO 执行的两个阶段都被阻塞了。
场景:阻塞 Socket、Java BIO。适用并发较小的网络应用,并发较大的不适用,因为一个请求 IO 阻塞进程,就要为每个请求分配一个进程(线程)来响应,开销大。
(二)非阻塞 I/O 模型 - Non-Blocking IO
图解:当用户进程发出 recv() 操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个错误码。一旦内核中的数据准备好了,并且又再次收到了用户进程的系统调用,那么它马上就将数据拷贝到了用户内存,然后返回。
特点:用户进程需要不断的主动询问内核数据好了没有,进程轮询调用,消耗 CPU 资源。
场景:SOCKET 设置 NON BLOCKING 属性。支持并发量小,不用及时响应的网络应用。
(三)I/O多路复用 - IO multiplexing
在 Linux 内核代码迭代过程中,依次支持了 SELECT、POLL、EPOLL 三种多路复用的网络 I/O 模型。
IO 多路复用的的基本原理是指单个线程就可以同时处理多个网络连接。 具体实现是 SELECT、POLL、EPOLL这些函数,会不断的轮询所负责的所有 socket,当某个 socket 有数据到达了,就通知用户进程。
图解:以 select 为例,当用户进程调用了 select,那么整个进程会被阻塞,而此时,内核会监视所有 select 负责的 socket,当任何一个 socket 中的数据准备好了,select 就会返回。这个时候用户进程再调用 recv 操作,将数据从内核拷贝到用户进程。
特点:IO 多路复用是阻塞在 select,poll,epoll 这样的系统调用之上,而没有阻塞在真正的I/O系统调用(如recv());专一进程解决多个进程 IO 的阻塞问题,性能好,Reactor模式。
场景:Java NIO,Nginx。适用高并发服务应用开发,一个进程/线程响应多个请求。
(四)信号驱动 I/O - Signal driven IO
我们也可以用信号,让内核在描述字就绪时发送 SIGIO 信号通知我们,称这种模型为信号驱动I/O(signal-driven I/O)。
应用进程使用 sigaction 系统调用,预先告知内核,向内核注册这样一个函数,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recv() 将数据从内核复制到应用进程中。
(五)异步 I/O 模型 - Asynchronous IO
图解:应用进程执行 aio_read() 系统调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
特点:不阻塞,一步到位。
场景: Java 7 AIO、高性能服务器,高性能高并发。
异步 IO 模型,要求等待数据和数据拷贝操作的两个处理阶段上都不能等待(blocking),内核自行去准备好数据并将数据从内核缓冲区中复制到应用进程的缓冲区,再通知应用进程读操作完成了,然后应用进程再去处理。
遗憾的是,Linux 的网络 IO 模型中是不存在异步 IO 的,Linux 的网络 IO 处理的第二阶段总是阻塞等待数据 copy 完成的。
04. Linux 网络 IO 模型比较
上图已经把 Linux 中的 IO 模型归档的很到位,还是稍微总结一下。前四种 IO 模型都是同步 IO 模型,主要区别在于第一阶段的处理不同,第二阶段的处理是相同的,都是在数据从内核复制到用户空间时,进程阻塞于 recv() 调用。而异步 IO 模型的处理都是非阻塞的,用户进程将整个 IO 操作交由内核去完成,内核完成后会发送通知。
好了,今天就扯这么多,希望大家能够喜欢。

从 Linux 操作系统谈谈 IO 模型(终)的更多相关文章
- [转载] Linux五种IO模型
转载:http://blog.csdn.net/jay900323/article/details/18141217 Linux五种IO模型性能分析 目录(?)[-] 概念理解 Lin ...
- Windows五种IO模型性能分析和Linux五种IO模型性能分析
Windows五种IO模型性能分析和Linux五种IO模型性能分析 http://blog.csdn.net/jay900323/article/details/18141217 http://blo ...
- (转载) Linux五种IO模型
转载:http://blog.csdn.net/jay900323/article/details/18141217 Linux五种IO模型及分析 目录(?)[-] 概念理解 Linux下 ...
- Linux 的 Socket IO 模型
前言 之前有看到用很幽默的方式讲解Windows的socket IO模型,借用这个故事,讲解下linux的socket IO模型: 老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系. 他 ...
- 网络通信 --> Linux 五种IO模型
Linux 五种IO模型 聊聊Linux 五种IO模型
- Linux五种IO模型(同步 阻塞概念)
Linux五种IO模型 同步和异步 这两个概念与消息的通知机制有关. 同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.比如,调用readfrom系统调用时,必须等待IO操 ...
- linux下的IO模型---学习笔记
1.linux文件系统和缓存 文件系统接口 文件系统-一种把数据组织成文件和目录的存储方式,提供了基于文件的存取接口,并通过文件权限控制访问. 存储层次 文件系统缓存 主存(通常时DRAM)的一块区域 ...
- 深入理解JAVA I/O系列六:Linux中的IO模型
IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大致描述了数据从外部磁盘向运行中程序的内存中移动的过程. 用户空间.内核空间 现在操作系统都是采用虚拟存储器, ...
- Linux五种IO模型性能分析
1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步: 所谓同步,就是在发出一个功能调用时, ...
随机推荐
- 关于在elasticSearch中使用聚合查询后只显示10个bucket的问题
先看下面es查询语句 { "size": 0, "aggs" : { "all_articleId" : { "terms&quo ...
- 第八次——非确定的自动机NFA确定化为DFA
NFA 确定化为 DFA 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合. 步骤: 1. ...
- 【04】openlayers 地图弹框
效果: 创建地图: //创建地图 var map = new ol.Map({ //设置显示地图的视图 view: new ol.View({ projection: 'EPSG:4326', //投 ...
- const 详解
简单分类: 常变量 const 类型 变量名 或者 类型 const 变量名 常引用 const 类型& 引用名 ...
- 适用于 macOS 下 2K 显示器开启 HiDPI 的简便解决方案
前阵子入手了一款2k的显示器用于mbp的拓展屏幕,但由于苹果系统的严格限制,只有在4K及以上显示器上才能开启自带的HiDPI进行缩放以达到retina显示屏的效果.2k显示器下的字体会偏小发虚,使用1 ...
- WordCount程序(Java)
Github项目地址:https://github.com/softwareCQT/web_camp/tree/master/wordCount 一.题目描述 实现一个简单而完整的软件工具(源程序特征 ...
- Spring Boot(十三):整合Redis哨兵,集群模式实践
前面的两篇文章(Redis的持久化方案, 一文掌握Redis的三种集群方案)分别介绍了Redis的持久化与集群方案 -- 包括主从复制模式.哨兵模式.Cluster模式,其中主从复制模式由于不能自动做 ...
- 洛谷 P1438 无聊的数列 题解
原题链接 首先,我们考虑用差分解决问题. 用 \(x_i\) 表示原数列,\(a_i = x_i - x_{i-1}\) 那么,先普及一下差分: 如果我们只需要维护区间加值,单点求值的话,你会发现两个 ...
- 【2019多校第一场补题 / HDU6578】2019多校第一场A题1001Blank——dp
HDU6578链接 题意 有一串字符串,仅由 {0,1,2,3}\{0, 1, 2, 3\}{0,1,2,3} 组成,长度为 nnn,同时满足 mmm 个条件.每个条件由三个整数组成:l.r.xl.r ...
- PyTorch 实战-张量
Numpy 是一个非常好的框架,但是不能用 GPU 来进行数据运算. Numpy is a great framework, but it cannot utilize GPUs to acceler ...