做网站的公司 贵阳,wordpress自动发货如何设置,网站建设费用选网络专业,店铺外卖网站怎么做目录零拷贝mmapsendFile总结零拷贝
要了解零拷贝#xff0c;首先得先了解一下传统 IO 的执行流程#xff0c;这里举个例子#xff0c;通过传统的 IO 进行网络传输来传输一个文件。 先上一张图#xff0c;这张图就代表了传统 IO 传输文件的流程。
读取文件的时候#xf…
目录零拷贝mmapsendFile总结零拷贝
要了解零拷贝首先得先了解一下传统 IO 的执行流程这里举个例子通过传统的 IO 进行网络传输来传输一个文件。 先上一张图这张图就代表了传统 IO 传输文件的流程。
读取文件的时候会从用户态切换为内核态同时基于 DMA 引擎将磁盘文件拷贝到内核缓冲区。
看到这里可能你就已经懵逼了什么是用户态和内核态什么是 DMA 拷贝我用大白话解释一下
首先用户态其实就是 CPU 在执行你的代码而内核态呢其实就是你没有那个权限去操作硬件所以只能交给系统去调用这个时候就是内核态。举个例子你的女朋友需要你修个电脑醒醒但凡有一粒花生米也不至于喝成这样我换个说法假如你同班的女同学想让你修个电脑但是宿管阿姨不肯放你进女生宿舍这个时候你就是用户态你不能进女生宿舍所以你只能让宿管阿姨内核态来帮你把电脑取出来。
那什么是 DMA 拷贝呢DMADirectMemoryAccess直接内存存取其实就是因为 CPU 老哥太累了所以找了个小弟就是 DMA 替他完成一部分的拷贝工作这样 CPU 就能去做其他事情了。
讲完了内核态和用户态还有 DMA 的大概意思我们接着回到刚才的 IO 流程中第一步我们将文件从磁盘文件读到了用户缓冲区此时经历了一次上下文切换和一次拷贝。
由内核态切换为用户态基于 CPU 把内核缓冲区的数据拷贝到用户缓冲区。
调用 socket 的输出流的 write 方法的话此时会从用户态切换到内核态同时基于 CPU把用户缓冲区里的数据拷贝到 Socket 缓冲区里去接着会有一个异步化的过程基于 DMA 引擎从 Socket 缓冲区里把数据拷贝到网络协议引擎里发送出去。
当 IO 操作完成之后又从内核态切换为用户态。
通过上面的步骤可以发现传统的 IO 操作执行有 4 次上下文的切换和 4 次拷贝是不是很繁琐。
零拷贝的话一般有 mmap 和 sendFile 两种一个一个来说。
mmap
mmap 是一种内存映射技术mmap 相比于传统的 IO 来说其实就是少了 1 次 CPU 拷贝而已上图。 传统 IO 里面从内核缓冲区到用户缓冲区有一次 CPU 拷贝从用户缓冲区到 Socket 缓冲区又有一次 CPU 拷贝。mmap 则一步到位直接基于 CPU 将内核缓冲区的数据拷贝到了 Socket 缓冲区。
之所以能够减少一次拷贝就是因为 mmap 直接将磁盘文件数据映射到内核缓冲区这个映射的过程是基于 DMA 拷贝的同时用户缓冲区是跟内核缓冲区共享一块映射数据的建立共享映射之后就不需要从内核缓冲区拷贝到用户缓冲区了。
虽然减少了一次拷贝但是上下文切换的次数还是没变。
RocketMQ 中就是使用的 mmap 来提升磁盘文件的读写性能。
sendFile
在 Linux 中提供 sendFile 函数实现了零拷贝依旧是先上图。 可以看到在图中已经没有了用户缓冲区因为用户缓冲区是在用户空间的所以没有了用户缓冲区也就意味着不需要上下文切换了就省略了这一步的从内核态切换为用户态。
同时也不需要基于 CPU 将内核缓冲区的数据拷贝到 Socket 缓冲区了只需要从内核缓冲区拷贝一些 offset 和 length 到 Socket 缓冲区。
接着从内核态切换到用户态从内核缓冲区直接把数据拷贝到网络协议引擎里去同时从 Socket 缓冲区里拷贝一些 offset 和 length 到网络协议引擎里去但是这个 offset 和 length 的量很少几乎可以忽略。
sendFile 整个过程只有两次上下文切换和两次 DMA 拷贝很重要的一点是这里完全不需要 CPU 来进行拷贝了所以才叫做零拷贝这里的拷贝指的就是操作系统的层面。
那你肯定会问那 mmap 里面有一次 CPU 拷贝为啥也算零拷贝只能说那不算是严格意义上的零拷贝但是他确实是优化了普通 IO 的执行流程就像老婆饼里也没有老婆嘛。
Kafka 和 Tomcat 内部使用就是 sendFile 这种零拷贝。
总结
传统 IO 执行的话需要 4 次上下文切换用户态 - 内核态 - 用户态 - 内核态 - 用户态和 4 次拷贝磁盘文件 DMA 拷贝到内核缓冲区内核缓冲区 CPU 拷贝到用户缓冲区用户缓冲区 CPU 拷贝到 Socket 缓冲区Socket 缓冲区 DMA 拷贝到协议引擎。
mmap 将磁盘文件映射到内存支持读和写对内存的操作会反映在磁盘文件上适合小数据量读写需要 4 次上下文切换用户态 - 内核态 - 用户态 - 内核态 - 用户态和3 次拷贝磁盘文件DMA拷贝到内核缓冲区内核缓冲区 CPU 拷贝到 Socket 缓冲区Socket 缓冲区 DMA 拷贝到协议引擎。