深入理解零拷贝技术

传统文件传输过程:

零拷贝技术

是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域,这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。通俗来讲,零拷贝就是一种避免CPU将数据从一块存储拷贝到另一块存储的技术,零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而提高数据的传输效率

问题

我们再看这个文件传输过程,我们只是搬运了一份数据,结果却搬运了四次,这种传统文件传输方式存在冗余的上下文切换和数据拷贝,在高并发的场景下,严重影响系统性能

所以,我们要减少用户态和内核态的上下文切换和数据拷贝的次数

解决方案:

MMAP+wirte

mmap()系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间,这样,操作系统内核与用户空间就不需要再进行任何的数据栲贝操作。

 buf = mmap(diskfd, len); 
 write(sockfd, buf, len);

应用程序调用mmap(),磁盘上的数据会通过DMA被拷贝的内核缓冲区,接着操作系统会把这段内核缓冲区与应用程序共享,这样就不需要把内核缓冲区的内容往用户空间拷贝。应用程序再调用write(),操作系统直接将内核缓冲区的内容拷贝到socket缓冲区中,这一切都发生在内核态,最后,socket缓冲区再把数据发到网卡去。该过程减少了一次拷贝

问题

使用mmap替代read很明显减少了一次拷贝,当拷贝数据量很大时,无疑提升了效率。但是使用mmap是有代价的。当你使用mmap时,你可能会遇到一些隐藏的陷阱。例如,当你的程序map了一个文件,但是当这个文件被另一个进程截断(truncate)时, write系统调用会因为访问非法地址而被SIGBUS信号终止。SIGBUS信号默认会杀死你的进程并产生一个coredump,如果你的服务器这样被中止了,那会产生一笔损失。

解决方案

1.为SIGBUS信号建立信号处理程序 当遇到SIGBUS信号时,信号处理程序简单地返回,write系统调用在被中断之前会返回已经写入的字节数,并且errno会被设置成success,但是这是一种糟糕的处理办法,因为你并没有解决问题的实质核心。

2.使用文件租借锁 通常我们使用这种方法,在文件描述符上使用租借锁,我们为文件向内核申请一个租借锁,当其它进程想要截断这个文件时,内核会向我们发送一个实时的RT_SIGNAL_LEASE信号,告诉我们内核正在破坏你加持在文件上的读写锁。这样在程序访问非法内存并且被SIGBUS杀死之前,你的write系统调用会被中断。write会返回已经写入的字节数,并且置errno为success。 我们应该在mmap文件之前加锁,并且在操作完文件后解锁:

sendfile

从Linux内核2.4版本开始起,对于支持网卡支持SG-DMA技术的情况下, 第一步,通过DMA将磁盘上的数据拷贝到内核缓冲区里; 第二步,缓冲区拷贝文件描述符和数据长度传到socket缓冲区, 这样网卡的SG-DMA控制器就可以直接将内核缓存中的数据栲贝到网卡的缓冲区里, 此过程不需要将数据从操作系统内核缓冲区栲贝到socket缓冲区中,这样就减少了一次数据栲贝

零栲贝技术的文件传输方式相比传统文件传输的方式,减少了2次上下文切换和数据栲贝次数,只需要2次上下文切换和数据栲贝次数,就可以完成文件的传输,而且2次的数据栲贝过程,都不需要通过CPU,2次都是由DMA来搬运。所以,总体来看,零栲贝技术可以把文件传输的性能提高至少一倍以上

零拷贝的好处



展开阅读全文

页面更新:2024-05-21

标签:技术   上下文   缓冲区   内核   操作系统   过程   文件   数据   用户   系统

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top