文章目录
- 前言
- 一、普通IO
- 二、mmap
- 三、sendfile
- 1. Linux2.1的sendfile
- 2. Linux2.4的sendfile
- 四、总结与扩展
- 1. 结论
- 2. 解释、扩展
- 参考
前言
概念: 没有发生CPU拷贝数据,都是DMA(直接内存访问)拷贝
优势:
- 减少内核态与用户态的切换
- 减少数据复制次数
- 避免CPU拷贝浪费CPU资源
- 整个内存空间只有一份数据
一、普通IO
应用程序想要读取磁盘文件并进行网络发送时,会发生4次上下文切换,4次数据拷贝
- 用户态的应用想要读取磁盘文件,会转换到内核态,通过DMA拷贝到内核缓冲区
- 内核态的数据通过CPU拷贝到用户态的用户缓冲区
- 用户态的用户缓冲区的数据通过CPU拷贝到内核态的Socket缓冲区
- 内核态的Socket缓冲区通过DMA拷贝到网络引擎,网络引擎发送结束后需要返回给用户态发送结果
二、mmap
通过对用户缓冲区和内核缓冲区建立映射,共享一块映射数据,不需要从内核缓冲区拷贝到用户缓冲区,因此:
应用程序想要读取磁盘文件并进行网络发送时,会发生4次上下文切换,3次数据拷贝
三、sendfile
1. Linux2.1的sendfile
Linux2.1时,提供了sendfile方法,数据直接从内核缓冲区CPU拷贝到Socket缓冲区,和用户态无关,因此:
应用程序想要读取磁盘文件并进行网络发送时,会发生3次上下文切换,3次数据拷贝
2. Linux2.4的sendfile
Linux2.4时,优化了sendfile方法,数据直接从内核缓冲区通过DMA拷贝到网络引擎,但是需要通过CPU拷贝少量位移信息,因此:
应用程序想要读取磁盘文件并进行网络发送时,会发生3次上下文切换,2次数据拷贝。没有通过CPU拷贝数据
四、总结与扩展
1. 结论
上下文切换次数 | 数据拷贝次数 | |
---|---|---|
普通IO | 4 | 2次DMA,2次CPU |
mmap | 4 | 2次DMA,1次CPU |
Linux2.1版sendfile | 3 | 2次DMA,1次CPU |
Linux2.4版sendfile | 3 | 2次DMA |
Linux2.4版本的sendfile才真正意义上实现了零拷贝
2. 解释、扩展
知识点联系:
IO-NIO-Netty-【RocketMQ、Dubbo】
sendfile-kafka
mmap-RocketMQ
什么是用户态与内核态。
参考
- Linux 零拷贝技术-mmap与sendFile
- 尚硅谷Netty视频33p-零拷贝原理解析