零拷贝技术

零拷贝

零拷贝主要的任务就是避免CPU将数据从一块存储拷贝到另外一块存储,主要就是利用各种零拷贝技术,避免让CPU做大量的数据拷贝任务,减少不必要的拷贝,或者让别的组件来做这一类简单的数据传输任务,让CPU解脱出来专注于别的任务。这样就可以让系统资源的利用更加有效。

用户态与内核态

用户态:只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取。

当一个进程在执行用户自己的代码时处于用户运行态(用户态),此时特权级最低,为3级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态。

内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序。

当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核 代码中执行。

所以,用户态和内核态取决于当前正在执行的代码是否属于内核代码。

用户态与内核态的转换

所有用户程序都是运行在用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作.

这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令

这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)

工作流程如下:

  1. 用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.

  2. 用户态程序执行陷阱指令

  3. CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问

  4. 这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务

  5. 系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果

文件IO过程

根据以上知识不能看出,传统的java代码在发送一个文件到另一台服务器上时,需要经过如下步骤。

零copy.png

注:利用DMA直接从磁盘复制到内存,不经过CPU的寄存器,所以称为DMA copy;先从内存到寄存器,然后寄存器到内核缓冲区,所以称为CPU copy。

以上流程经过了四次上下文切换,四次copy。所以看起来效率并不高,所以需要采取零拷贝(zero-copy)技术来提示性能。

零拷贝流程

零copy2.png

以上(sendfile实现零拷贝)流程,可以看到整个流程只做了两次copy。同时也减少了上下文切换。

总结

零拷贝(zero-copy)并不是copy次数为零,而是减少系统的copy次数和cpu上下文切换的频率。许多中间件为了提示数据传递的效率,会用到零拷贝技术,比如kafka等。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容