OS 零拷贝

无 DMA 的I/O 过程 :

  1. CPU 发出对应的指令给磁盘控制器,然后返回
  2. 磁盘控制器收到指令后,就将数据放到磁盘控制器的缓冲区中,并产生中断
  3. CPU 收到中断,就将磁盘控制器的缓冲区的数据一次一个字节地读进寄存器,再将寄存器里的数据写到内存

image.png

缺点 : 数据传输 , 要 CPU 全程接入 , 浪费 CPU 资源

DMA (直接内存访问 (Direct Memory Access) ) :

  • I/O 与内存交换数据时 , 不用 CPU 搬运 , 通过 DMA 传输

image.png

传统 I/O : 要进行 4 次用户/内核态的上下文切换 , 4 次数据拷贝

image.png

零拷贝

零拷贝 : 能减少上下文切换数 , 数据拷贝数

零拷贝技术实现方式 :

  • mmap + write
  • sendfile

mmap+ write

  • read() : 把内核缓冲区的数据拷到用户的缓冲区
  • mmap() : 把内核缓冲区的数据映射到用户空间, 内核与用户空间就不用数据拷贝

mmap 过程 :

  1. 调用 mmap() , DMA 将磁盘数据拷到内核缓冲区
  2. 应用进程共享内核缓冲区
  3. 调用 write(), 将内核缓冲区数据拷到 socket 缓冲区 (内核态进行,由 CPU 搬运)
  4. DMA 将 socket 缓冲区拷到网卡缓冲区

image.png

总结 :

  • mmap() 代替 read() , 能减少一次数据拷贝过程
  • CPU 还是要将内核缓冲区数据拷到 socket 缓冲区
  • 要 4 次上下文切换

sendfile

sendfile() : 直接将内核缓冲区数据拷到 socket 缓冲区里,不用用户态

  • 只有 2 次上下文切换, 3 次数据拷贝

image.png

真零拷贝

网卡支持 SG-DMA (The Scatter-Gather Direct Memory Access)

  • 不用将内核缓冲区数据拷到 socket 缓冲区
ethtool -k eth0 | grep scatter-gather

# scatter-gather: on

sendfile() 过程 :

  1. DMA 将磁盘数据拷到内核缓冲区
  2. 将缓冲区描述符和数据长度传到 socket 缓冲区
  3. SG-DMA 直接将内核缓存数据拷到网卡缓冲区

image.png

零拷贝 (Zero-copy) : DMA传输数据, 不用 CPU 搬运数据

  • 只用 2 次上下文切换和数据拷贝次数

PageCache

零拷贝用了内核缓冲区 (PageCache) , 让零拷贝性能更高

PageCache 优点 :

  • 缓存最近被访问的数据: 缓存热点数据
  • 预读功能: 读取周边数据

传输文件太大(GB) , PageCache 问题 :

  • 长时间被大文件占据, 热点小文件无法利用缓存
  • 大文件无法利用缓存 , 耗费 DMA 拷到 PageCache 耗时

猜你喜欢

转载自blog.csdn.net/qq_44226094/article/details/131710434
os