当前位置: 首页 > 后端技术 > Java

IO零拷贝

时间:2023-04-01 21:18:41 Java

1.相关概念用户态和内核态:Linux操作系统架构分为用户态和内核态。内核主要控制计算机的硬件资源,为上层应用程序提供运行支持。用户态是上层应用程序的活动空间。应用程序的执行需要内核的支持,如CPU资源、存储资源、IO资源等,用户态使用内核提供的访问接口,即系统调用来使用这些资源。直接内存访问DMA:DMA允许外设和内存存储之间直接IO数据传输,过程不需要CPU参与虚拟内存:计算机内存管理的一种技术手段,可以是连续的也可以是非连续的内存,它也可以是磁盘空间。虚拟内存的两个特点:一是多个虚拟地址可以指向同一个物理内存地址;另一种是虚拟内存空间可以大于实际可用的物理地址。虚拟内存的第一个特点是可以将内核空间地址和用户空间地址映射到同一个物理地址,这样DMA就可以操作对内核和用户空间进程同时可见的缓冲区。零拷贝:没有数据从一个存储区域复制到另一个存储区域。当然,零拷贝也不是真的不拷贝数据,而是通过一些手段,尽量减少数据的拷贝(数据不需要在用户空间和内核空间来回拷贝),从而释放CPU,减少上下文切换,减少内存使用以提高程序性能。的目标。内存映射:Linux提供的mmap系统调用可以将一段用户内存映射到内核空间。当映射成功时,用户对这块内存区域的修改可以直接反映到内核空间中;修改也直接反映在用户空间中。由于这种映射关系,用户态和内核态之间不需要复制数据,提高了数据传输的效率。用户态和内核态示意图:虚拟内存示意图:2.传统IO实现的文件传输应用调用read(),上下文切换到内核,DMA将磁盘数据复制到内核的缓存空间。read()返回,上下文切换到用户态,CPU拷贝数据到用户缓存空间,应用程序调用write(),上下文再次切换到内核,CPU拷贝数据到内核socket缓存write()返回,上下文再次切换到用户态,DMA拷贝socket缓存数据到网卡缓存上,已经有4次上下文切换,4次数据拷贝。3、mmap(内存映射)+write实现的零拷贝应用发出mmap系统调用,用户态切换到内核态。发生上下文切换,然后通过DMA将磁盘文件中的数据复制到内核空间缓冲区。mmap系统调用返回,内核空间切换到用户态,又一次上下文切换发生。但是不需要把数据从内核空间copy到用户空间,因为内核空间和用户空间共享这个buffer。write系统调用发出后,用户态再次切换到内核态,数据会从内核空间缓冲区复制到内核空间的socket中。bufferwrite系统调用返回,内核态切换到用户空间,DMA拷贝sokcetbuffer数据到网卡。有4个上下文切换和3个数据副本。sendfile系统调用是通过sendfile实现的零拷贝发出的,引起用户空间到内核空间的上下文切换,然后通过DMA引擎将磁盘文件的内容拷贝到内核空间缓冲区,再从中拷贝数据内核空间缓冲区到socket相关缓冲区的sendfile系统调用返回,导致内核空间Context切换到用户空间。DMA将内核空间中socketbuffer中的数据异步传输到网卡中。有2个上下文切换和3个数据副本。5.具有DMA收集和复制功能的sendfile的零拷贝实现是从Linux2.4版本开始由操作系统提供的。SG-DMA的scatter和gather方法是直接从内核空间缓冲区中读取数据到网卡,而不是将内核空间缓冲区中的数据拷贝到socket缓冲区中。具体过程如下:应用程序发送sendfile调用,用户态切换到内核态,通过DMA将数据复制到内核缓冲区。与之前的sendfile不同的是,数据不再从内核缓冲区复制到socket缓冲区,而是将文件描述符fd(内核缓冲区内存地址和内核缓冲区偏移地址)复制到socket缓冲区。sendfile系统调用返回,内核态切换到用户态,DMA通过内核缓冲内存地址和偏移量将数据复制到网卡。这里发生了2次上下文切换和2次数据拷贝。六、splice实现的零拷贝Linux在2.6.17版本引入了splice系统调用,不仅不需要硬件支持,还实现了两个文件描述符之间的数据归零。复制。splice系统调用可以在内核空间的读缓冲区(readbuffer)和网络缓冲区(socketbuffer)之间建立管道,从而避免两者之间的CPU拷贝操作。具体过程如下:用户发起splice调用,用户态切换到内核态,CPU使用DMA将数据拷贝到内核缓冲区,内核缓冲区和socket缓冲区之间建立管道,CPU使用DMA从socketbuffer中拷贝数据到网卡splice调用返回,内核态切换到用户态。总共有2次上下文切换,两种数据复制复制方式CPU复制DMA复制系统调用上下文切换传统方式(read+write)22read/write4内存映射(mmap+write)12mmap/write4sendfile12sendfile2sendfile+DMAgathercopy02sendfile2splice02sendfile2参考文章:零拷贝原理高性能IO背后的linux零拷贝原理零拷贝技术netty零拷贝实现原理重新认识Java中的内存映射(mmap)