2、Linux IO模型分析
一、IO面向对象
IO参与者有应用、系统、用户空间、磁盘.下面列举不同的面对对象的支持情况.
面向对象 | 支持IO类型 |
面向java | bio、nio、aio |
面向磁盘存储 | 线性结构、链式结构 |
面向系统内核 | 直接IO、缓存IO(标准IO) |
面向用户、系统 | 同步阻塞IO[bio] 、 同步非阻塞IO[线程池bio]、异步阻塞 IO(多路复用I/O )[select、poll、epoll]、 信号驱动IO |
二、直接与缓存IO区别
IO面向内核 | 区别 |
直接IO概念 | 程序访问数据不经过内核缓存区,直接访问磁盘、网卡等其他设备的IO过程 |
缓存IO概念 | 程序访问数据,先将数据copy到系统内核,然后从系统内核copy到用户空间 |
直接IO与缓冲IO区别 | 程序访问数据,数据是否进过系统内核,操作系统为了系统安全和缓存的需要,用户读取数据需要先读取到系统内核,然后从系统内核copy到用户空间,这种模式隔离用户空间和系统空间提高系统的安全,数据缓存到系统内核,不必每次读取数据都从磁盘读取提高程序的性能,但是在不需要反复数据读取处理的场景(比如kafka),缓存I/O会多一层读取内核操作,浪费cpu和内存资源。关于直接I/O Linux使用很多技术待I/O模型技术实现分解. |
三、IO与磁盘存储
磁盘存储结构 | 解释说明 |
线性结构 | 程序存储数据时,申请一块连续的磁盘空间,然后将数据顺序写入磁盘,此种模式硬盘无需寻址,写入性能接近内存写入速度 |
链式结构 | 程序存储数据时候,申请一块非连续的磁盘空间,写入磁盘时候程序需要寻址速度慢。 两种区别:程序存储时候申请硬盘是连续磁盘空间,还是逻辑连续的磁盘空间,连续的磁盘空间程序写入性能好,但是硬盘空间利用率差,逻辑连续的硬盘资源反之 |
四、同步、异步,阻塞、非阻塞定义?
IO名词 | 面对对象 | 区别 |
同步 | IO会阻塞用户进程 | 进程触发IO操作是否会阻塞用户进程,用户的cup此时是否释放,所以同步异步针对的是用户进程 |
异步 | IO不会阻塞用户进程 | |
阻塞 | 用户进程需等待内核copy数据到用户空间的过程 | 触发read()操作后,系统内核是否会立刻返回状态还是等待, 所以阻塞非阻塞是针对操作系统内核。 |
非阻塞 | 用户进程不需等待内核copy数据到用户空间的过程 |
五、同步阻塞
用户发起IO操作后,用户进程阻塞等待内核响应,此时系统内核发生上下文切换,等待内核将数据copy到用户空间,这个过程看似紧密有序,但是有用户线程和内核线程等待,所以同步阻塞I/O是一种低效I/O
六、同步非阻塞
用户发起IO操作后,用户进程阻塞等待内核响应,此时系统内核立刻返回成功,当read()响应完成,系统内核会产生一个信号或者基于一个线程回调函数完成IO过程。
linux同步非阻塞IO模型:当用户发起IO请求,用户进程阻塞,此时read()响应错误代码,内核响应未就绪,程序需要多次请求确认内核就绪,严格意义上讲此时内核是阻塞的,在等待内核响应有一定的时间间隔,所以同步非阻塞I/O也是一种低效I/O。
七、异步阻塞IO[多路复用IO模型]
当用户发起IO请求,此时用户进程不被阻塞,此时内核配置的IO是非阻塞的IO,操作系统会阻塞select来监视内核是否就绪,如果内核就绪就通知应用处理。此IO模型也叫多路复用IO模型,只是缓解内核阻塞,但是高性能的IO操作仍然会有性能问题,目前是linux主流的IO模型。
总结:此I/O模型是linux最成熟稳定的I/O模型,linux做大量的技术优化(比如:select、poll、epoll),许多高性能框架都是基于此I/O模型,比如 netty,mina等。
linux异步阻塞IO实现
多路复用 | IO模型 | 性能 | 成熟度 | 内核处理方式 |
select | 差 | 高 | 对全部的文件描述符遍历,不管是否准备好,浪费cup资源 | |
poll | 中 | 高 | poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个文件描述符对应的设备状态。相比select不用全局遍历.但是poll本质还是要顺序遍历不断从用户传递过来的文件描述符状态,因此性能会受到一定限制 | |
epoll | 好[linux默认io] | 差 | 内核callback通知用户进程io状态,这种模式从下面几点保证其性能好相对poll模式 设计算法、不重复copy 文件描述符号状态 |
八、异步非阻塞
用户发起IO请求,此时用户进程不被阻塞,此时内核配置的IO是非阻塞的IO,当内核就绪后回调通知用户线程完成IO处理流程,linux 信号驱动IO、异步IO都是此类IO模型.
8.1、信号驱动IO
信号驱动IO模型:首先开启套接口信号驱动IO功能,并通过系统调用sigaction 执行一个信号处理函数(此系统调用立即返回,进程继续工作,它是非阻塞的)。当数据准备就绪时,就为该进程生成一个SIGIO信号,通过信号回调通知应用程序调用recvfrom 来读取数据,并通知主循环函数处理数据.
8.2、异步IO
异步IO:告知内核启动某个操作,并让内核在整个操作完成后(包括将数据从 内核复制到用户自己的缓冲区)通知我们。这种模型与信号驱动模型的主要区别是:信号 驱动IO由内核通知我们何时可以开始一个IO操作;异步IO模型由内核通知我们IO 操作何时已经完成.
九、epoll相对优点?
现比较epoll的优点主要和select、poll对比, 信号驱动IO,异步IO不再本次讨论范围类,这两种IO模型还不太成熟.epoll解决随着文件描述符增加,poll、select性能的线性下降.
9.1、epoll数据结构跟优秀
IO模型 | 数据结构 | 时间复杂度 |
select | 链表 | O(n) |
poll | 链表 | O(n) |
epoll | 红黑树+链表 | O(logn) |
9.1.1、select、poll数据结构比较
select、poll数据结构是链表结构,他们两者的区别是select遍历全部的用户文件描述符,poll遍历用户copy的文件描述符号数组,降低了遍历的数量,其他方式没有变化.
9.1.2、epoll高性能原因
新建epoll描述符 == epoll_create()
epoll把用户关心的文件描述符上的事件放在内核里的一个事件表中,从而无须像select和poll那样每次调用都要重复传入文件描述符集或事件集。
epoll需要使用一个额外的文件描述符,来唯一标识内核中的这个事件表。 这个文件描述符使用如下epoll_create函数来创建
添加或者删除所有待监控的连接 == epoll_ctl()
epoll_ctl函数添加进来的事件都会被放在红黑树的某个节点内,所以,重复添加是没有用的,红黑树本身插入和删除性能比较好,时间复杂度O(logN)
返回的活跃连接 == epoll_wait( epoll描述符 )
epoll_wait只需要检查rdlist双向链表中是否有存在注册的事件
9.1.3、poll、epoll性能测试
select、poll的内部实现机制相似,性能差别主要在于向内核传递参数以及对fdset的位操作上,另外,select存在描述符数的硬限制,不能处理很大的描述符集合。这里主要考察poll与epoll在不同大小描述符集合的情况下性能的差异。程序会统计在不同的文件描述符集合的情况下,1s内poll与epoll调用的次数。统计结果如下,从结果可以看出,对poll而言,每秒钟内的系统调用数目虽集合增大而很快降低,而epoll基本保持不变,具有很好的扩展性。在10万文件描述符的场景下,epoll的性能是poll的1000倍.
描述符集合大小 | poll | epoll |
1 | 331598 | 258604 |
10 | 330648 | 297033 |
100 | 91199 | 288784 |
1000 | 27411 | 296357 |
5000 | 5943 | 288671 |
10000 | 2893 | 292397 |
25000 | 1041 | 285905 |
50000 | 536 | 293033 |
100000 | 224 | 285825 |
十、IO模型与硬件
6.1、IO读写流程
1、IO读流程
用户空间读请求-->Linux内核空间-->在pageCache查询缓存-->未查询到os内核在内存映射的目标数据(缺页)-->获取逻辑地址(获取page对应块地址)-->块地址获取磁盘物理地址-->通过SASI指令操作硬盘读取物理地址内容-->数据返回到系统内核(此过程通过DMA技术直接copy到内存,不需要cup参与)-->数据通过内核返回到用户空间
2、IO写流程
用户空间写请求-->将文件写入pageCache-->获取逻辑地址(获取page对应块地址)-->块地址获取磁盘物理地址-->通过SASI指令操作硬盘读取物理地址内容-->pageCache在合适的时机将脏页刷新到磁盘
3、IO读写流程总结
系统在读写的时候参与方可能有 cup、内存、硬盘、网卡、显卡等等外接设备,分析过程发现三个特点
- 这个读写过程都有经过操作系统内核
- 读写过程都经过用户空间
- 通过DMA技术对第三方外设进一步抽象,让CPU无需关注外设copy数据到系统内核过程。
6.2、IO模型与linux协议
1.4、名词解释:
硬件名词解释
DMA技术:它允许某些电脑内部的硬件子系统(外设),可以独立地直接读写系统内存,而不需中央处理器介入处理,同等情况下降低cup负担。
PIC总线:cpu访问其他pic设备的通道。
SAS控制器:一种新型的磁盘链接技术。
MCU微控单元:一种微型计算机简称单片机。
MMU内存管理单元:分页内存管理单元,功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制。
LBA逻辑地址块:存储设备物理地址与逻辑地址映射关系
Linux名词解释
脏页:被修改过的页
扇区:磁盘存储的最小单位
磁盘块:文件系统读写数据的最小单位
页:内存存储的最小单位,他是位于内存和文件系统之间的缓存区域,操作系统通过地址映射将文件系统映射为页的级别。
pageCache:页高速缓冲存储器,简称页高缓。page cache的大小为一页,通常为4K。在linux读写文件时,它用于缓存文件的逻辑内容,从而加快对磁盘上映像和数据的访问。
机型硬盘容量:硬盘容量大小=磁头数×柱面数×扇区数×每扇区字节数
相关文章
- GitHub 的替代品
- Oh My GitHub 1.0 is out!
- 【已解决】Windows系统使用WSL安装的Linux系统怎么设置root密码
- php大小写转换
- php如何在某个时间上加一天?一小时? 时间加减
- php字符串比较
- PHP中include()与require()
- php实现网站访客数量统计的方法(简单实现,不能防刷新)
- PHP循环输出二维数组的数据
- PHP统计当前在线用户数实例
- PHP 的 UNICODE 编码和解码
- PHP100上的图片上传程序
- PHP GD库
- 详解:macOS/Linux如何挂载磁盘?如何开机自动挂载/卸载磁盘?
- Windows Server 2008 R2x64 IIS7+PHP5.6 错误 500.0
- PHP实现微信公众号企业号自定义菜单接口示例
- PHP过滤html注释
- PHP库存管理系统的设计之词汇恶补
- JQ + PHP + TrackMore物流信息跟踪
- 入门级 – 码云(Gitee),GitHub 教程