在某种程度上减少甚至完全避免不必要 CPU 数据拷贝操作,是一种 I/O 操作优化技术
铺垫些基础知识
-
进程内存空间
操作系统会给每个进程分配内存空间,一部分是用户空间,一部分是内核空间。
内核空间:受保护,操作系统内核可以访问,用户空间无权限访问,用来做内存分配、进程调度等
用户空间:程序进程的空间
-
CPU 工作状态
用户态、内核态。
看进程运行于什么空间:内核空间则为内核态;用户空间则为用户态。
-
上下文切换
内核在 CPU 上对进程或者线程进行切换,一般在系统调用的时候会发生,比如从用户态切换到内核态。
-
DMA
Direct Memory Access(直接存储器访问),将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输,相当于帮 CPU 拷贝数据,让 CPU 腾出时间干别的事。
IO 执行流程对比
以一个场景为例:后端接收一个请求,将本地存储的一个文件返回给前端。
-
普通 IO
如图所示,过程包括 4 次数据拷贝和 4 次上下文切换。
-
mmap
mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系,比如可以将内核中的读缓冲区与用户空间的缓冲区进行映射,所有的 IO 都在内核空间中完成,减少拷贝次数。
如图所示,过程包括 3 次数据拷贝和 4 次上下文切换。
-
sendfile
sendfile 表示表示两个文件描述符之间进行传递,在内核中操作,免去了内核缓冲区和用户系统缓冲区之间的数据拷贝。
如图所示,过程包括 3 次拷贝和 2 次上下文切换。
-
sendfile + DMA scatter/gather
Linux之后升级了sendfile
,引入 SG-DMA 技术,其实就是对 DMA 拷贝加入了scatter/gather
,可以直接从内核空间缓冲区中将数据读取到网卡。
如图所示,过程包括 2 次拷贝和 2 次上下文切换,而且真正做到了无 CPU 拷贝。