深入理解零拷贝技术实现原理(从表象到Linux内核文件管理机制的底层实现)

(一)先了解一下什么是零拷贝,以及零拷贝的优点?

(1 )零拷贝其实就是从用户端发起一次需要用到磁盘文件的请求的时候,会通过网络IO进行后去你想要的文件,但是你要知道程序都是运行在Linux机器上的,而且这件事情也是又程序去做的,因为传统的IO需要拷贝四次,所以就有了网络IO的问题,那么瓶颈也就出了。为了优化这一操作,把IO四次拷贝通过优化到2 次拷贝,就称为“零拷贝”,传统的具体的传统流程是:
**
1. 用户程序需要去请求服务器上磁盘的资源,然后Linux内核会去调用DMA去拷贝磁盘文件复制到Linux内核空间的
page cache【这里后面会深入分析这个玩意】**中,这是第一次拷贝

2. 因为我们的程序是运行在Linux服务器上的,而且我们的服务也就是一个进程而已,但是如果程序需要刚刚我们从磁盘拷贝过来的那个资源文件,此时是不能直接访问的,也就是说程序不能直接访问Linux内核,大概是为了保护Linux内核系统的正常运行吧,所以需要从刚刚的page cache中拷贝到用户空间中的buffer cache缓存中,这是第二次拷贝

3. 因为用户客户端发出的请求,所以刚刚拷贝的文件一般都需要经过程序加工处理一些业务逻辑,然后需要把数据返回给客户端,那么此时数据是在用户空间的,但是发送的话,需要Linux内核调用然后才能发送,所以需要从用户空间拷贝到网络的Socket缓冲区,这是第三次拷贝

4. 最后一次就是Linux内核中的DMA去从Socket复制到网络中去发送返回给客户端结果,这是第四次拷贝。

深入理解零拷贝技术实现原理(从表象到Linux内核文件管理机制的底层实现)_第1张图片

(2)而零拷贝的流程是

  1. 直接省略调了 第二步,和第三步的流程,这样就大大提高了IO性能问题

补充一下DMA:

DMA 直接内存存取,是允许外设组件将I/O数据直接传送到主存储器中并且传输不需要CPU的参与,
以此将CPU解放出来去完成其他的事情。,相较于中断方式,减少cpu中断次数,不用cpu拷贝数据

(二)那么Linux是如何实现这种零拷贝的方式呢?

其实这里就用到了Linux 内核的文件 Cache 管理机制来进行实现的,在 Linux 的实现中,文件 Cache 分为两个层面,一是 Page Cache,另一个 Buffer Cache,每一个 Page Cache 包含若干 Buffer Cache。内存管理系统和 VFS 只与 Page Cache 交互,内存管理系统负责维护每项 Page Cache 的分配和回收,同时在使用 memory map 方式访问时负责建立映射;VFS 负责 Page Cache 与用户空间的数据交换。而具体文件系统则一般只与 Buffer Cache 交互,它们负责在外围存储设备和 Buffer Cache 之间交换数据

在Linux-2.4版本之前,其实page cache 和 buffer cache 是分开的,分别是两个独立的,所以在之后的版本中在文件读写时,以page为单位进行处理。而对下,在数据向device进行刷新时,就是page cache中以buffer_head(block)为单位进行处理。真正的把cache刷盘到磁盘上。
深入理解零拷贝技术实现原理(从表象到Linux内核文件管理机制的底层实现)_第2张图片

(1)将Cache项映射到用户空间,使得应用程序可以像使用内存指针一样访问文件,Memory map访问Cache的方式在内核中是采用请求页面机制实现的

  • 当我们应用程序调用mmap(图中1),陷入到内核中后调用do_mmap_pgoff(图中2)该函数从应用程序的地址空间中分配一段区域作为映射的内存地址,并使用一个VMA(vm_area_struct)结构代表该区域,之后就返回到应用程序(图中3)
  • 然后当应用程序访问mmap所返回的地址指针时(图中4),由于虚实映射尚未建立,会触发缺页中断(图中5)
  • 之后系统会调用缺页中断处理函数(图中6),在缺页中断处理函数中,内核通过相应区域的VMA结构判断出该区域属于文件映射,于是调用具体文件系统的接口读入相应的Page Cache项(图中7、8、9),并填写相应的虚实映射表
  • 经过这些步骤之后,应用程序就可以正常访问相应的内存区域了
    深入理解零拷贝技术实现原理(从表象到Linux内核文件管理机制的底层实现)_第3张图片

你可能感兴趣的:(【Kafka】,零拷贝,Linux内核)