mysql io模型_五种IO模型透彻分析

1.基础

在引入IO模型前,先对io等待时某一段数据的"经历"做一番解释。如图:

d9bda4dec5cee3d0076a92bb895e6dd6.png

当某个程序或已存在的进程/线程(后文将不加区分的只认为是进程)需要某段数据时,它只能在用户空间中属于它自己的内存中访问、修改,这段内存暂且称之为app buffer。假设需要的数据在磁盘上,那么进程首先得发起相关系统调用,通知内核去加载磁盘上的文件。但正常情况下,数据只能加载到内核的缓冲区,暂且称之为kernel buffer。数据加载到kernel buffer之后,还需将数据复制到app buffer。到了这里,进程就可以对数据进行访问、修改了。

现在有几个需要说明的问题。

(1).为什么不能直接将数据加载到app buffer呢?

实际上是可以的,有些程序或者硬件为了提高效率和性能,可以实现内核旁路的功能,避过内核的参与,直接在存储设备和app buffer之间进行数据传输,例如RDMA技术就需要实现这样的内核旁路功能。

但是,最普通也是绝大多数的情况下,为了安全和稳定性,数据必须先拷入内核空间的kernel buffer,再复制到app buffer,以防止进程串进内核空间进行破坏。

(2).上面提到的数据几次拷贝过程,拷贝方式是一样的吗?

不一样。现在的存储设备(包括网卡)基本上都支持DMA操作。什么是DMA(direct memory access,直接内存访问)?简单地说,就是内存和设备之间的数据交互可以直接传输,不再需要计算机的CPU参与,而是通过硬件上的芯片(可以简单地认为是一个小cpu)进行控制。

假设,存储设备不支持DMA,那么数据在内存和存储设备之间的传输,必须由内核线程占用CPU去完成数据拷贝(比如网卡不支持DMA时,内核负责将数据从网卡拷贝到kernel buffer)。而DMA就释放了计算机的CPU,让它可以去处理其他任务,DMA也释放了从用户进程切换到内核的过程,从而避免了用户进程在这个拷贝阶段被阻塞。

再说kernel buffer和app buffer之间的复制方式,这是两段内存空间的数据传输,只能由内核占用CPU来完成拷贝。

所以,在加载硬盘数据到kernel buffer的过程是DMA拷贝方式,而从kernel buffer到app buffer的过程是CPU参与的拷贝方式。

(3).如果数据要通过TCP连接传输出去要怎么办?

例如,web服务对客户端的响应数据,需要通过TCP连接传输给客户端。

TCP/IP协议栈维护着两个缓冲区:send buffer和recv buffer,它们合称为socket buffer。需要通过TCP连接传输出去的数据,需要先复制到send buffer,再复制给网卡通过网络传输出去。如果通过TCP连接接收到数据,数据首先通过网卡进入recv buffer,再被复制到用户空间的app buffer。

同样,在数据复制到send buffer或从recv buffer复制到app buffer时,是内核占用CPU来完成的数据拷贝。从send buffer复制到网卡或从网卡复制到recv buffer时,是DMA方式的拷贝,这个阶段不需要切换到内核,也不需要计算机自身的CPU。

如下图所示,是通过TCP连接传输数据时的过程。

60e24f07b11df4f2103d33f514e536f6.png

(4).网络数据一定要从kernel buffer复制到app buffer再复制到send buffer吗?

不是。如果进程不需要修改数据,就直接发送给TCP连接的另一端,可以不用从kernel buffer复制到app buffer,而是直接复制到send buffer。这就是零复制技术。

例如,如果httpd进程不需要访问和修改任何数据,那么将数据原原本本地复制到app buffer再原原本本地复制到send buffer然后传输出去的过程中,从kernel buffer复制到app buffer的过程是可以省略的。使用零复制技术,就可以减少一次拷贝过程,提升效率。

当然,实现零复制技术的方法有多种,见我的另一篇结束零复制的文章:

以下是以httpd进程处理文件类请求时比较完整的数据操作流程。

bfb4bd268806b44c89790ad2c7838482.png

大致解释下:客户端发起对某个文件的请求,通过TCP连接,请求数据进入TCP的recv buffer,再通过recv()函数将数据读入到app buffer,此时httpd工作进程对数据进行一番解析,知道请求的是某个文件,于是发起read系统调用,于是内核加载该文件,数据从磁盘复制到kernel buffer再复制到app buffer,此时httpd就要开始构建响应数据了,可能会对数据进行一番修改,例如在响应首部中加一个字段,最后将修改或未修改的数据复制(例如send()函数)到send buffer中,再通过TCP连接传输给客户端。

2. I/O模型

所谓的IO模型,描述的是出现I/O等待时进程的状态以及处理数据的方式。围绕着进程的状态、数据准备到kernel buffer再到app buffer的两个阶段展开。其中数据复制到kernel buffer的过程称为数据准备阶段,数据从kernel buffer复制到app buffer的过程称为数据复制阶段。请记住这两个概念,后面描述I/O模型时会一直用这两个概念。

本文某些地方以httpd进程的TCP连接方式处理本地文件为例,请无视httpd是否真的实现了如此、那般的功能,也请无视TCP连接处理数据的细节,这里仅仅只是作为方便解释的示例而已。

再次说明,从硬件设备到内存的数据传输过程是不需要CPU参与的,而内存间传输数据是需要内核线程占用CPU来参与的。

2.1 Blocking I/O模型

如图:

86fe950179ff4ffac136ba1c9bb0ca23.png

假设客户端发起index.html的文件请求,httpd需要将index.html的数据从磁盘中加载到自己的httpd app buffer中,然后复制到send buffer中发送出去。

但是在httpd想要加载

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值