面试经常问零拷贝吧?
网上的很多博客零拷贝讲解很生涩吧,就算你背下来了跟面试官讲,他极大可能会打断你......找了网上很多资料,终于可以用能理解的方式把零拷贝这个讲清楚了
零拷贝的考点
1.为什么要用零拷贝 从传统文件传输的弊端开始分析,传统文件传输主要是在用户空间和内核空间拷贝来完成文件的传输。会涉及4次拷贝和4次上下文切换,对高并发场景来说开销极大,零拷贝技术只用2次拷贝和2次上下文切换就可以完成数据的传输,极大提升了传输的效率 2. 那你能说说传统拷贝的具体流程吗 用户系统调用read(), 完成用户态到内核态的切换,CPU发送指令到DMA,DMA发送指令给磁盘控制器,磁盘控制器读取足够的数据到磁盘缓冲区,然后发送一个中断指令给DMA,DMA就将磁盘缓冲区的数据拷贝到内核缓冲区,发送中断信号给CPU,CPU完成内核缓冲数据到用户空间。用户就调用write()系统函数,完成相应的写操作,然后又会把用户空间的数据拷贝到socket缓冲区,socket缓冲区把数据拷贝到网卡完成传输
可见有很多操作是不必要的,比如把内核数据拷贝到用户空间,但用户空间不对数据做任何的修改,我们为什么不直接内核拷贝到socket缓冲区呢?
那你说零拷贝是怎么减少拷贝次数和上下文切换的? 在传输文件的过程中,主要是write()和read()两个系统调用,那零拷贝主要有两种实现方式: 1. mmap和write 2. sendfile
mmap和write替换传统的write和read;所以还是两次系统调用,只是拷贝的次数少了,上下文切换次数没少。前面不是要把内核缓冲区中的数据拷贝到用户空间吗,那mmap系统调用,就省略了这一步,用户空间和内核空间共享,就是用户空间可以直接访问内核空间,不用在拷贝了,所以减少了一次拷贝。但这并不是真正的零拷贝
sendfile这个系统调用可以完成整个文件的传输过程,他只用3次数据拷贝,1次系统调用,2次上下文切换就可以完成整个过程。首先,用户调用sendfile(),磁盘文件通过DMA拷贝到内核空间,这时直接可以把内核空间的数据拷贝到socket缓存区,再拷贝到网卡,就行。
后面又有了新的优化,用了一个特殊的网卡设施,就可以直接把内核缓冲区中的数据拷贝到网卡,只需要2次数据拷贝,这就是真正的零拷贝
你说了DMA拷贝,你能详细给我介绍介绍吗? DMA 就是直接内存存储,他是替代CPU搬运数据,提供CPU的利用率。 原来没有DMA的时候,用户调用read()函数,传达信息给CPU,CPU会传达信息给磁盘控制器,磁盘控制器读取数据到磁盘缓冲区,给CPU发送中断,CPU再把数据读入自己的寄存器,然后在把数据拷贝到用户空间,这样CPU参与了整个数据的搬运,所以后面有了DMA来代替。 零拷贝适合传输大文件吗 不适合,零拷贝会使用到内核缓冲区,也就是PageCache,PageCache是磁盘高速缓冲区,有两个主要功能,就是换成最近访问的数据,和预读功能。 那如果用零拷贝传输大文件,那PageCache会被大文件沾满,一些热点的小文件数据就会被淘汰,这样就失去了PageCahe的功能,没必要多一次这个拷贝。
所有传输大文件,一般是异步I/O和直接I/O,直接I/O就是绕过PageCache,直接把磁盘缓冲区的数据拷贝到内核缓冲区。