零拷贝是指计算机执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,进而减少上下文切换以及CPU的拷贝时间。它是一种IO操作优化技术。
Kafka的特性之一就是高吞吐率,原因之一就是因为底层使用ZeroCopy技术,直接将磁盘无需拷贝到用户空间,而是直接将数据通过内核空间传递输出,数据并没有抵达用户空间。
1、传统IO的执行流程
传统的IO流程包括read以及write的过程
- read:将数据从磁盘读取到内核缓存区中,在拷贝到用户缓冲区
- write:先将数据写入到socket缓冲区中,最后写入网卡设备
传统IO的执行过程:
- 用户进程调用read等系统调用向操作系统发出IO请求,请求读取数据到自己的内存缓冲区中。自己进入阻塞状态,上下文切换:用户态切换到内核态
- 操作系统收到请求后,进一步将IO请求发送磁盘。DMA(Direct Memory Access) 控制器,将数据从磁盘拷贝到内核缓冲区,此时不占用CPU
- CPU把内核缓冲区数据拷贝到用户应用缓冲区,上下文从内核态切换至用户态,同时read函数返回数据
- 应用进程通过write,发起IO调用,上下文从用户态切换至内核态
- CPU将缓冲区的数据拷贝到socket缓冲区
- DMA控制器将数据从socket缓冲区拷贝到网卡设备,上下文从内核态切换至用户态,同时write数据返回
从而得知,传统I/O经过了四次上下文切换,四次拷贝 (两次CPU拷贝,两次DMA拷贝)
2、DMA
DMA(Direct Memory Access),直接内存访问。DMA本质上是一块主板上独立的芯片,允许外设设备和内存存储器之间直接进行IO数据传输,其过程不需要CPU的参与。
DMA模式下,DMA就是CPU的一个代理,它负责了一部分的拷贝工作,从而减轻了CPU的负担。DMA的优点就是:中断少,CPU负担低。
DMA读取过程
- 用户进程调用read等系统调用向操作系统发出IO请求,请求读取数据到自己的内存缓冲区中。自己进入阻塞状态。
- 操作系统收到请求后,进一步将IO请求发送DMA。然后让CPU干别的活去。
- DMA进一步将IO请求发送给磁盘。
- 磁盘驱动器收到DMA的IO请求,把数据从磁盘读取到驱动器的缓冲中。当驱动器的缓冲区被读满后,向DMA发起中断信号告知自己缓冲区已满。
- DMA收到磁盘驱动器的信号,将磁盘驱动器的缓存中的数据拷贝到内核缓冲区中。此时不占用CPU。这个时候只要内核缓冲区的数据少于用户申请的读的数据,内核就会一直重复步骤3跟步骤4,直到内核缓冲区的数据足够多为止。
- 当DMA读取了足够多的数据,就会发送中断信号给CPU。
- CPU收到DMA的信号,知道数据已经准备好,于是将数据从内核拷贝到用户空间,系统调用返回。
3、传统I/0与零拷贝对比
传统I/O
- 文件在磁盘中数据被copy到内核缓冲区
- 从内核缓冲区copy到用户缓冲区
- 用户缓冲区copy到内核与socket套接字相关的缓冲区
- 数据从socket缓冲区copy到相关协议引擎发送出去
零拷贝
- 文件在磁盘中数据被copy到内核缓冲区
- 从内核缓冲区copy到内核与socket相关的缓冲区。
- 数据从socket缓冲区copy到相关协议引擎发送出去
4、零拷贝实现
零拷贝并非不拷贝数据,而是减少上线文切换次数以及CPU拷贝次数;实现零拷贝的方式如下:
4.1 mmap技术
mmap利用了操作系统虚拟内存的特点特点,将内核空间和用户空间的虚拟地址映射到同一个物理地址,所以将内核中的读写缓冲区与用户空间的缓冲区进行映射,所有的IO都在内核中完成。mmap+write实现的零拷贝流程如下:
- 用户进程通过调用mmap方法向操作系统内核发起IO调用,上下文从用户态切换至内核态
- 操作系统收到请求后,进一步将IO请求发送磁盘。DMA(Direct Memory Access) 控制器,将数据从磁盘拷贝到内核缓冲区,此时不占用CPU
- 上下文从内核态切换回用户态,mmap方法返回
- 用户进程通过调用write方法向操作系统内核再次发起IO调用,上下文从用户态切换至内核态
- CPU将内核缓冲区的数据拷贝到socket缓冲区
- DMA控制器将数据从socket缓冲区拷贝到网卡设备,上下文从内核态切换至用户态,同时write数据返回
mmap+write实现的零拷贝其中发生了4次上线文切换以及3次拷贝(2次DMA拷贝+1次cpu拷贝)

4.2 sendfile
sendfile表示在两个文件描述符之间传输数据,它是在操作系统内核中操作的,减少了用户态和内核态的上下文切换,去除了数据从内核缓冲区和用户缓冲区之间的拷贝操作,因此可以使用它来实现零拷贝。
sendfile零拷贝流程如下:
- 用户进程通过sendfile方法向操作系统发起I/O调用,上下文从用户态切换至内核态
- 操作系统收到请求后,进一步将IO请求发送磁盘。DMA(Direct Memory Access) 控制器,将数据从磁盘拷贝到内核缓冲区,此时不占用CPU
- CPU将读缓冲区中的数据拷贝到socket缓冲区
- DDMA控制器将数据从socket缓冲区拷贝到网卡设备,上下文从内核态切换至用户态,sendfile返回
由此可知通过sendfile实现的零拷贝其中发生了2次上下文切换以及3次拷贝(2次DMA拷贝+1次cpu拷贝)


1177

被折叠的 条评论
为什么被折叠?



