NIO之零拷贝

NIO的零拷贝的0指的是,0次需要cpu的拷贝,DMA拷贝不算在里面。零拷贝可以大大提高我们数据传输的效率。

传统IO

在这里插入图片描述

  • 磁盘 -> 内核空间的缓存(DMA)
  • 内核空间的缓存 -> 用户态中的程序缓存
  • 对数据做一系列操作
  • 用户态中的程序缓存 -> 内核空间的的socket缓存
  • 内核空间的socket缓存->网卡缓存(DMA)
  • 网络发送(或拷贝到磁盘)!

在一次传统的IO中,操作系统一共进行了2次拷贝,4次操作系统状态转换

2次拷贝:注意,磁盘到内核态的读写是通过DMA拷贝,外部设备(磁盘,U盘)不通过CPU直接与系统内存交换数据。所以是2次拷贝
4次系统状态切换:详情如下
在这里插入图片描述
tips: 为什么数据不直接从磁盘拷贝到用户程序空间呢?通过局部性原理我们知道,当我们从磁盘上取一个数据的时候,有很大可能下一次读取的数据就是本次读取数据周围的数据。因此操作系统为了提高性能,在读取数据的时候,会先把该目标数据周围的数据(NTFS下是4KB为单位)也一并读到操作系统的read buffer中,下次读取时,就有很大可能命中read buffer,减少了磁盘IO

NIO 零拷贝
不需要对数据进行操作
windows Linux2.4以下

在这里插入图片描述

  • sendFile()
    该版本下的sendFile,只需要2次状态切换,即 开始: 用户态->内核态(read buffer 到 socket buffer)->用户态,但是还需要把Read buffer中的数据通过cpu完整的拷贝到Socket Buffer,所以不能算是真正的0拷贝。

    该种方法是2次切换,1次拷贝
Linux 2.4以后

在这里插入图片描述

  • sendFile()
    该版本下,sendFile()直接将内核态的Read buffer发送到NIC的 buffer,只有部分描述信息,如缓存位移,描述符经过socket buffer,通过这些信息,DMA直接把数据拷贝到外围设备缓存中。由于数据描述信息量很少,基本可以视作0,所以这也是0拷贝
需要对数据进行操作

当我们需要在用户空间对数据进行处理时,上述方法都不能解决问题

  • mmap,把内核态的缓存空间用户态的缓存空间映射到一块物理地址,实现共享,减少了内核态缓存到用户态缓存的一次拷贝。(因为使用mmap后,内存共享了,进程直接对内核空间映射到进程的虚拟地址进行读写就行,无需拷贝,但系统状态还是需要切换的)

该种方法是4次上下文切换,3次拷贝(2次DMA拷贝)。

3次上下文切换:
  • 发出mmap系统调用,用户态->内核态,通过DMA将磁盘文件拷贝到read buffer中
  • mmap系统调用返回,内核态->用户态,此时用户空间和内核空间中的read buffer共享一块缓冲区内存空间
  • 用户修改数据,并发出write调用,用户态->内核态,read buffer中的数据通过cpu拷贝到socket buffer
  • write调用返回,socker buffer通过DMA拷贝到外围设备。内核态->用户态
零拷贝的再次理解
  • 我们说零拷贝,是从cpu的角度来说的,减少对cpu占用可以大大提升效率,而DMA拷贝无法避免。
  • 零拷贝不仅仅带来更少的数据复制,还能带来其他的性能优势,例如更少的上下文切换,更少的CPU缓存伪共享以及无CPU校验和计算。
mmap和sendFile的区别
  • mmap适合小数据读写, sendFile适合大文件传输
  • mmap需要4次上下文切换,1次数据拷贝(还有);sendFile需要3次上下文切换,最小号2次数据拷贝
  • sendFile可以利用DMA,减少CPU拷贝,mmap则不能(必须从内核拷贝到Socket缓冲区)

参考
浅谈NIO与零拷贝
尚硅谷韩顺平Netty视频教程(2019发布)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值