上架学姐 8 张图,就可以搞懂「零拷贝」了,原来

前言
磁盘可以说是计算机系统最慢的硬件之一 , 读写速度相差内存10倍以上 , 所以针对优化磁盘的技术非常的多 , 比如零拷贝、直接I/O、异步I/O等等 , 这些优化的目的就是为了提高系统的吞吐量 , 另外操作系统内核中的磁盘高速缓存区 , 可以有效的减少磁盘的访问次数 。
这次 , 我们就以「文件传输」作为切入点 , 来分析I/O工作方式 , 以及如何优化传输文件的性能 。
上架学姐 8 张图,就可以搞懂「零拷贝」了,原来
文章图片
在没有DMA技术前 , I/O的过程是这样的:
CPU发出对应的指令给磁盘控制器 , 然后返回;
磁盘控制器收到指令后 , 于是就开始准备数据 , 会把数据放入到磁盘控制器的内部缓冲区中 , 然后产生一个中断;
CPU收到中断信号后 , 停下手头的工作 , 接着把磁盘控制器的缓冲区的数据一次一个字节地读进自己的寄存器 , 然后再把寄存器里的数据写入到内存 , 而在数据传输的期间CPU是无法执行其他任务的 。
为了方便你理解 , 我画了一副图:
上架学姐 8 张图,就可以搞懂「零拷贝」了,原来
文章图片
可以看到 , 整个数据的传输过程 , 都要需要CPU亲自参与搬运数据的过程 , 而且这个过程 , CPU是不能做其他事情的 。
简单的搬运几个字符数据那没问题 , 但是如果我们用千兆网卡或者硬盘传输大量数据的时候 , 都用CPU来搬运的话 , 肯定忙不过来 。
计算机科学家们发现了事情的严重性后 , 于是就发明了DMA技术 , 也就是直接内存访问(DirectMemoryAccess)技术 。
什么是DMA技术?简单理解就是 , 在进行I/O设备和内存的数据传输的时候 , 数据搬运的工作全部交给DMA控制器 , 而CPU不再参与任何与数据搬运相关的事情 , 这样CPU就可以去处理别的事务 。
【上架学姐 8 张图,就可以搞懂「零拷贝」了,原来】那使用DMA控制器进行数据传输的过程究竟是什么样的呢?下面我们来具体看看 。
上架学姐 8 张图,就可以搞懂「零拷贝」了,原来
文章图片
具体过程:
用户进程调用read方法 , 向操作系统发出I/O请求 , 请求读取数据到自己的内存缓冲区中 , 进程进入阻塞状态;
操作系统收到请求后 , 进一步将I/O请求发送DMA , 然后让CPU执行其他任务;
DMA进一步将I/O请求发送给磁盘;
磁盘收到DMA的I/O请求 , 把数据从磁盘读取到磁盘控制器的缓冲区中 , 当磁盘控制器的缓冲区被读满后 , 向DMA发起中断信号 , 告知自己缓冲区已满;
DMA收到磁盘的信号 , 将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中 , 此时不占用CPU , CPU可以执行其他任务;
当DMA读取了足够多的数据 , 就会发送中断信号给CPU;
CPU收到DMA的信号 , 知道数据已经准备好 , 于是将数据从内核拷贝到用户空间 , 系统调用返回;
可以看到 , 整个数据传输的过程 , CPU不再参与数据搬运的工作 , 而是全程由DMA完成 , 但是CPU在这个过程中也是必不可少的 , 因为传输什么数据 , 从哪里传输到哪里 , 都需要CPU来告诉DMA控制器 。
早期DMA只存在在主板上 , 如今由于I/O设备越来越多 , 数据传输的需求也不尽相同 , 所以每个I/O设备里面都有自己的DMA控制器 。
如果服务端要提供文件传输的功能 , 我们能想到的最简单的方式是:将磁盘上的文件读取出来 , 然后通过网络协议发送给客户端 。
传统I/O的工作方式是 , 数据读取和写入是从用户空间到内核空间来回复制 , 而内核空间的数据是通过操作系统层面的I/O接口从磁盘读取或写入 。
代码通常如下 , 一般会需要两个系统调用:
read(file,tmp_buf,len);write(socket,tmp_buf,len);
代码很简单 , 虽然就两行代码 , 但是这里面发生了不少的事情 。


推荐阅读