零拷贝
大约 2 分钟
零拷贝
零拷贝(Zero-copy)是一种计算机操作技术,主要减少数据在不同存储区域之间的复制次数,提高数据传输效率.
一、关键术语
原来获取数据:
CPU >> 磁盘控制器 >> 内核缓冲区
DMA直接内存访问技术:
DMA控制器 >> 磁盘控制器 >> 内核缓冲区
- 用户缓冲区
应用程序自己分配的内存区域
- 内核缓冲区
操作系统内核空间中的一块内存区域。内核缓冲区则在文件 I/O 过程中起到临时存储数据的作用
- 页缓存
Page Cache
操作系统在内存中维护的一块区域,主要通过将最近访问过的文件页面存储在内存中,减少对磁盘的实际 I/O 操作次数。
- socket缓冲区
发送和接收数据时临时存储数据的内存区域,靠近网卡.
二、数据流转
- 应用程序Read文件
磁盘 >> 内核缓冲区 >> 页缓存(Page Cache) >> 用户缓冲区
- 应用程序Read文件且所需数据在页缓存中
页缓存(Page Cache) >> 用户缓冲区
- 应用程序Write数据
用户缓冲区 >> 内核缓冲区 >> 磁盘
- 应用程序Read文件发送网卡
磁盘 >> 内核缓冲区 >> 页缓存(Page Cache) >> 用户缓冲区 >> Socket缓冲区 >> 网卡
三、零拷贝技术
- mmap + write
内核缓冲区 >>(直接映射)>> 到用户空间
- sendfile
内核缓冲区里 >>(skip用户缓冲区直接拷贝)>> socket 缓冲区 >> 网卡
- SG-DMA
内核缓冲区里 >> (跳过用户\Socket缓冲区直接拷贝) >> 网卡
四、使用零拷贝的项目
- Nginx
http {
...
# 内核缓冲区数据直接到Socket缓冲区
sendfile on
...
}
- kafka
# Kafka是Java项目
# Kafka底层传输文件使用了 `Java NIO 库` 的 `transferTo`
# transferTo 底层使用了 sendfile
# 内核缓冲区 >> 直接到Socket缓冲区 (跳过用户缓冲区)
long transferForm(FileChannel fileChannel,long position,long count) throws IOException {
return fileChannel.transferTo(position,count,socketChannel);
}