零拷贝总结

1.缓冲区

一个java进程发起read请求加载数据大致的流程图:
在这里插入图片描述

2.虚拟内存

在这里插入图片描述
所有现代操作系统都使用虚拟内存,使用虚拟地址取代物理地址,好处是:
1)多个虚拟地址可以指向同一个物理内存地址
2)虚拟内存空间可大于实际可用的物理地址;
利用第一条特性可以把内核空间地址和用户空间的虚拟地址映射到同一个物理地址,这样DMA就可以填充对内核和用户空间进程同时可见的缓冲区了。

3.传统的文件数据

在这里插入图片描述
步骤:
1)系统调用read方法,上下文切换到内核态(切换),DMA把磁盘数据复制到内核缓冲区
2)read调用返回,上下文切换到用户进程(切换),CPU把数据复制到用户的缓冲区
3)write系统调用,上下文切换到内核态(切换),CPU把数据复制到内核Socket缓冲区
4)write调用返回,上下文切换到用户进程(切换)
5)DMA把数据复制到网卡缓冲区
总结:4次上下文切换 + 2次CPU复制 + 2次DMA复制。

4.多次拷贝原因分析

1)操作系统为了保护系统不被应用程序破坏,设置了用户态和内核态。用户态想要获取系统资源(例如访问硬盘), 必须通过系统调用进入到内核态, 由内核态获取到系统资源,再切换回用户态返回应用程序。
2)出于异步写入避免每次写都需要IO操作等性能优化, OS在内核态中也增加了一个"内核缓冲区",读取数据时先读取到kernel buffer, 再由kernel buffer复制到应用程序buffer。

5.系统调用mmap()来代替read

在这里插入图片描述
在这里插入图片描述
步骤:
1)系统调用mmap(),上下文切换到内核态(切换),DMA把磁盘数据复制到内核缓冲区。
2)操作系统把这段内核缓冲区与应用程序共享(就不需要往用户空间拷贝了)。
3)mmap()调用返回,上下文切换到用户态(切换)。
4)write系统调用,上下文切换到内核态(切换),CPU把内核缓冲区数据复制到内核缓冲区
5)write调用返回,上下文切换到用户进程(切换)
6)DMA把数据复制到网卡缓冲区(协议栈)
总结:
1)4次上下文切换 + 1次CPU复制 + 2次DMA复制。
2)有陷阱,当程序map了一个文件,但是被另一个进程截断(truncate)时, write系统调用会因为访问非法地址而被SIGBUS信号终止,会使你进程被杀掉。可以使用文件锁来解决。

6.sendfile调用(内核版本2.1)

在这里插入图片描述
总结:
2次上下文切换 + 1次CPU拷贝 + 2次DMA拷贝。

7.sendfile调用(内核版本2.4)

在这里插入图片描述
步骤:
1)应用程序开始读文件的操作
2)应用程序发起系统调用, 从用户态进入到内核态(第一次上下文切换)
3)内核态中把数据从硬盘文件读取到内核中间缓冲区
4)内核态中把数据在内核缓冲区的位置(offset)和数据大小(size)两个信息追加(append)到socket的缓冲区中去
5)网卡的buf上根据socekt缓冲区的offset和size从内核缓冲区中直接拷贝数据
6)从内核态返回到用户态(第二次上下文切换)
相比于sendfile2.1的优化点:
sendfile2.1中会将内核缓冲区的全量数据CPU拷贝到Socket缓冲区。而sendfile2.4中的CPU拷贝只是offset、size等一点点信息。
总结:
2次上下文切换 + 2次DMA拷贝。

8.零拷贝的零体现在哪

零拷贝,是从OS角度来看,内核中没有数据是重复。sendFile 2.4中,只有 kernel buffer 有一份数据,是零拷贝。而mmap和sendFile 2.1 方式,在内核中有 2 份数据,算不上零拷贝。

java零拷贝

1)MappedByteBuffer
2)DirectByteBuffer
3)Channel-to-Channel传输

其他零拷贝

1)Netty零拷贝
2)RocketMQ采用零拷贝mmap+write
3)kafka中存在大量的网络数据持久化和磁盘文件通过网络发送的过程,使用了sendfile零拷贝方式;

10.总结

1)mmap方式:4次上下文切换 + 1次CPU复制 + 2次DMA复制。
2)sendFile 2.1 方式:2次上下文切换 + 1次CPU拷贝 + 2次DMA拷贝。
3)sendFile 2.4方式:2次上下文切换 + 2次DMA拷贝。
4)零拷贝,更少的数据复制,更少的上下文切换,更少的 CPU 缓存伪共享以及无 CPU 校验和计算。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
零拷贝(sendfile)是一种技术,它可以在数据传输过程中减少CPU的拷贝次数,从而提高数据传输的效率。在使用零拷贝技术时,数据可以直接从文件系统的缓冲区传输到网络缓冲区,而无需经过中间的用户空间。这样可以减少上下文切换的次数和数据拷贝的次数,提高数据传输的速度。 在实现零拷贝的过程中,sendfile函数是常用的方法之一。它可以将文件描述符(fd_in)所指向的文件内容直接传输到另一个文件描述符(fd_out)所指向的文件或者套接字中,而无需经过用户空间。这样可以减少数据拷贝的次数和CPU的拷贝次数。 另外,使用DMA(直接内存访问)技术也可以进一步减少CPU的拷贝次数。DMA允许外设直接访问内存,而无需通过CPU进行数据传输。通过结合sendfile和DMA gatter技术,可以实现彻底减少CPU拷贝次数的零拷贝操作。 总结起来,零拷贝(sendfile)是一种通过减少CPU的拷贝次数来提高数据传输效率的技术。它可以通过直接将数据从文件系统的缓冲区传输到网络缓冲区,而无需经过用户空间,从而减少上下文切换和数据拷贝的次数。结合DMA技术,可以进一步减少CPU的拷贝次数,实现真正意义上的零拷贝操作。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [一篇文章彻底弄懂零拷贝底层原理](https://blog.csdn.net/CoderBruis/article/details/114155953)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [详细讲解零拷贝机制的进化过程](https://blog.csdn.net/gegeyanxin/article/details/129409997)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值