零拷贝这个知识点在我过往的学习中从未有过接触,这次青训营有关零拷贝的课程很好的填补了这个空缺,这篇笔记就对零拷贝这个知识点做一个简单梳理。
传统文件传输过程
文件传输最普遍的一个场景就是,用户从本地发送一个文件通过网络传递给另一个用户,这一操作可以简化为两个系统调用
// 读取文件内容到缓冲区
read(file, buf, len);
// 通过socket发送数据给客户端
write(socket, buf, len);
深入这两个系统的调用的执行过程,我们可以得到以下流程图
可以发现在文件传输过程中,发生了四次内核上下文切换以及四次数据拷贝。我们知道,频繁的内核上下文切换资源开销比较大,所以在大批量文件传输的场景下势必会造成性能瓶颈。而从内核空间拷贝数据到用户空间同样也需要耗费较多资源。人们为此开始探究提升性能的方法,重点在于减少上下文切换以及CPU拷贝的次数,零拷贝的概念应运而生。
零拷贝
零拷贝并不是指的0次数据拷贝,而是减少用户态和内核态之间的CPU拷贝次数以及减少上下文切换次数。在介绍几种零拷贝的实现方式之前,先简要说一下CPU的数据拷贝方式
CPU数据拷贝方式
-
I/O轮询
I/O轮询是最初计算机的数据拷贝方法,即CPU不断去查询数据是否准备就绪,一旦就绪进行拷贝,这种方式实现非常简单,但缺点也显而易见,其会占用CPU全部资源,导致运行效率低下。
-
系统中断
系统中断相比于I/O轮询方法,在一定程度上释放了CPU资源。它的核心思想是,在数据就绪前,CPU只需要发送一次I/O请求,随后就可以转去执行其他指令,当数据就绪后,I/O设备会发起一次中断请求,通知CPU数据准备就绪。但这种方式也有缺点,即在大数据量传输的情况下,CPU会反复中断从而影响整体执行效率。
-
DMA
DMA就是在CPU和I\O设备之间设立了一层代理,CPU只需向DMA发起I\O请求,而后DMA会完成数据获取以及数据拷贝的工作,彻底减少了一次CPU拷贝。
零拷贝实现
- mmap + write
- sendfile
- sendfile + gather DMA
- splice
总结
用户要根据自己的业务需求选择合适的零拷贝方式,传输过程中如果需要修改文件内容,只能采用mmap的方式实现零拷贝。