zero copy,没有cpu参与的拷贝
零拷贝技术,大多数网络服务器都是client-server形式的.当程序想将磁盘上的文件发给服务器时要通过:
硬盘 > 内核缓冲区 > 程序 > socket > 协议栈 4次拷贝
用户态 > 内核态 > 用户态 > 内核态 > 用户态. 4次态的切换
mmap优化:
硬盘 > 内核缓冲区 > socket > 协议栈
用户态 > 内核态 > 用户态 > 内核态 > 用户态
mmap内存映射技术是一种优化方式
将物理文件映射到内核缓冲区,同时用户空间也可以共享这个地址.此时可以直接从内核缓冲区传到socket fd中,减少了一次拷贝,但是不减少上下文切换
改进后的技术省去了操作系统read给用户程序的过程,直接将数据发给socketfd,利用了内核的sendfile系统调用,nio的FileChannel.transferto()方法就是这样实现的,
sendfile 减少了一次上下文切换
硬盘 > 内核缓冲区 > socket > 协议栈
用户态 > 内核态 > 用户态.
sendfile优化
linux又做了修改,减去了内核缓冲区到socket fd的过程!向socketfd的buffer中追加数据在内核buffer中的位置和偏移量.socket变成了一个文件描述符.描述kernel buffer的内存地址和偏移量
硬盘 > 内核缓冲区 >> socket > 协议栈
用户态 > 内核态 > 用户态
socket缓冲区的意思就是socket的fd的send-q 和 recv-q
缓存与缓冲区是不同的
缓存是将数据保存起来以备调用,但是没有数据则还是回去读磁盘的
缓冲区则是减少数据的调用次数.
零拷贝:数据从磁盘->内核缓冲区-> -> nic
从操作系统角度来看,只有内核缓冲区有一份数据,其他地方不存有数据,之前几种方式在socket buf里还有相同数据,零拷贝指的是cpu没有参与拷贝,dma是参与的.
还带来了性能优势,如上下文切换,无cpu参与
mmap与sendfile的区别
mmap适合小数据量,sendfile适合大数据
mmap需要4次拷贝,3次切换 sendfile需要3次切换 2次数据拷贝
软件应用
kafka,当有文件通过网卡来时,读到用户空间内,然后通过mmap系统调用挂载files 和 devices.于是直接写文件
消费者通过sendfile系统调用将文件读到内核给消费者
例如kafka,netty,都是用了零拷贝技术