零拷贝

I/O主要为:网络IO(本质是socket文件读取)、磁盘IO
每次IO,都要经由两个阶段:
① 将数据从文件先加载至内核内存空间(缓冲区),等待数据准备完成,时间较长
② 将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短

 由上图可知,经过两个阶段,共产生了四次数据拷贝,即使使用了DMA来处理了与硬件的通讯,CPU仍然需要处理两次数据拷贝,与此同时,在用户态与内核态也发生了多次上下文切换,无疑也加重了CPU负担

而传统的Linux 操作系统数据拷贝也是基于标准 I/O 接口进行的,即 I/O 操作会将数据在操作系统内核地址空间的缓冲区和应用程序地址空间定义的缓冲区之间进行传输。这样做的好处就是,当后续请求的数据已经存放在操作系统的高速缓冲存储器中,那么就不需要再进行实际的物理磁盘 I/O 操作,可以减少磁盘 I/O 的操作。但是也还有一个问题,数据传输过程中的数据拷贝操作却导致了极大的 CPU 开销,限制了操作系统有效进行数据传输操作的能力

 

零拷贝应运而生

零拷贝:是一种避免cpu将数据从一块存储拷贝到另一块存储的技术,针对操作系统中的设备驱动程序、文件系统、网络协议堆栈衍生出各种零拷贝技术,避免让CPU做大量的数据拷贝任务,内核驱动程序处理I/0数据环节减少不必要的拷贝,让CPU解脱出来专注于别的任务,有效改善数据传输性能

优点:

① 避免操作系统内核缓冲区之间进行数据拷贝操作。

② 避免操作系统内核和用户应用程序地址空间这两者之间进行数据拷贝操作。

③ 用户应用程序可以避开操作系统直接访问硬件存储。

④ 数据传输尽量让 DMA 来做。

将多种操作结合在一起,将任务需要进行拷贝的数据先缓存起来,避免不必要的系统调用和上下文切换,对数据进行处理尽量让硬件来做

 

 

 从2.1版内核开始,Linux引入了sendfile来简化操作,sendfile系统调用利用DMA引擎将文件内容拷贝到内核缓冲区去,然后将带有文件位置和长度信息的缓冲区描述符添加socket缓冲区去,这一步不会将内核中的数据拷贝到socket缓冲区中,省去了read() 和write() 这两个系统调用,DMA引擎会将内核缓冲区的数据拷贝到协议引擎中去,避免了最后一次拷贝,使用sendfile不仅减少了数据拷贝的次数,还减少了上下文切换,数据传送始终只发生在kernel space

 

参考文章:零拷贝原理详解

posted @ 2022-05-12 13:08  蚂蚁力量  阅读(157)  评论(0)    收藏  举报