RocketMQ零拷贝原理

1、什么是零拷贝?

零拷贝是指CPU不需要在应用内存和内核内存之间拷贝数据消耗资源。

2、零拷贝的优势?

(1)避免不必要的CPU拷贝,让CPU解脱出来去执行其他的任务;
(2)减少内存带宽的占用;
(3)减少用户空间和操作系统内核空间之间的上下文切换;

3、数据拷贝的实现方式有哪些?

3.1、 传统的数据拷贝

在这里插入图片描述
(1)读取系统调用导致上下文从用户模式切换到内核模式。第一个副本由DMA引擎执行,该引擎从磁盘读取文件内容并将其存储到内核地址空间缓冲区中。
(2)将数据从内核缓冲区复制到用户缓冲区,然后读取的系统调用返回。调用返回导致上下文从内核切换回用户模式。现在,数据存储在用户地址空间缓冲区中,并且可以重新开始。
(3)写系统调用导致上下文从用户模式切换到内核模式。执行第三次复制以再次将数据放入内核地址空间缓冲区。但是,这次将数据放入另一个缓冲区中,该缓冲区专门与套接字关联。
(4)write系统调用返回,创建我们的第四个上下文开关。独立且异步地,当DMA引擎将数据从内核缓冲区传递到协议引擎时,发生第四次复制。

3.2、mmap

在这里插入图片描述
(1)mmap系统调用使DMA引擎将文件内容复制到内核缓冲区中。然后与用户进程共享缓冲区,而无需在内核和用户内存空间之间执行任何复制。
(2)写系统调用使内核将数据从原始内核缓冲区复制到与套接字关联的内核缓冲区中。
(3)第三份复制发生在DMA引擎将数据从内核套接字缓冲区传递到协议引擎时。

使用mmap + write方法时存在隐患:
当您在内存中映射文件时,然后调用write方法,但另一个进程将同一个文件截断时,总线错误信号SIGBUS将中断您的写入系统调用,因为您执行了错误的内存访问。该信号的默认行为是杀死进程并转储内核,这不是网络服务器最理想的操作。

有两种方法可以解决此问题:
(1)第一种方案是为SIGBUS信号安装信号处理程序,然后在处理程序中简单地调用return。通过这样做,write系统调用返回中断前写入的字节数,并将errno设置为success。这是一个不好的解决方案,只能解决症状而不是引起问题的原因。由于SIGBUS表示该过程出现了严重问题,因此我不建议使用此解决方案。
(2)第二种方案涉及从内核进行文件租赁(在Microsoft Windows中称为“机会锁定”)。这是解决此问题的正确方法。通过在文件描述符上使用租赁,您可以与特定文件的内核进行租赁。然后,您可以从内核请求读/写租约。当另一个进程试图截断正在传输的文件时,内核会向您发送一个实时信号RT_SIGNAL_LEASE信号。它告诉您内核正在破坏对该文件的写或读租约。在程序访问无效地址并被SIGBUS信号杀死之前,您的写调用被中断。写调用的返回值是中断之前写的字节数,并且errno将被设置为成功。

3.3 sendfile

在这里插入图片描述
(1)sendfile系统调用使DMA引擎将文件内容复制到内核缓冲区中。然后,数据被内核复制到与套接字关联的内核缓冲区中。
(2)第三份复制发生在DMA引擎将数据从内核套接字缓冲区传递到协议引擎时。

您可能想知道如果另一个进程截断了我们通过sendfile系统调用传输的文件会发生什么情况。如果我们不注册任何信号处理程序,则sendfile调用将简单返回其在中断之前传输的字节数,并且errno将被设置为成功。
但是,如果在调用sendfile之前从内核获得了对该文件的租约,则其行为和返回状态是完全相同的。在sendfile调用返回之前,我们还获得了RT_SIGNAL_LEASE信号。

到目前为止,我们已经能够避免让内核创建多个副本,但是我们仍然只剩下一个副本。也可以避免吗?绝对在硬件的帮助下。为了消除内核完成的所有数据重复,我们需要一个支持收集操作的网络接口。这只是意味着等待传输的数据不需要在连续的内存中;它可以分散在各个存储位置。
在内核版本2.4中,修改了套接字缓冲区描述符以适应这些要求-在Linux中称为零拷贝。这种方法不仅减少了多个上下文切换,而且还消除了处理器进行的数据重复。

3.4 、支持收集的硬件可以从多个内存位置收集数据,从而消除另一个副本。

在这里插入图片描述

(1)sendfile系统调用导致DMA引擎将文件内容复制到内核缓冲区中。
(2)没有数据被复制到套接字缓冲区中。相反,只有包含数据位置和长度信息的描述符才会附加到套接字缓冲区。DMA引擎将数据直接从内核缓冲区传递到协议引擎,从而消除剩余的最终副本。
因为数据实际上仍然是从磁盘复制到内存和从内存复制到导线,所以有些人可能会认为这不是真正的零拷贝。不过,从操作系统的角度来看,这是零拷贝,因为数据不会在内核缓冲区之间重复。使用零拷贝时,除了避免拷贝之外,还可以获得其他性能优势,例如更少的上下文开关、更少的CPU数据缓存污染和无CPU校验和计算。

4、参考文献

https://www.ibm.com/developerworks/cn/java/j-zerocopy/
https://www.linuxjournal.com/article/6345

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值