零拷贝和页缓存
2023-03-02 11:33:25 0 举报
零拷贝和页缓存
作者其他创作
大纲/内容
零 Copy 并不是真的不进行数据 Copy,其实还是需要进行两次数据 Copy 的,只不过这两次都是通过 DMA 进行 Copy 的,无需 CPU 参与,所以叫做零 Copy。
用户态
Page Cache
从左上图中可以看出,从数据读取到发送一共经历了四次数据拷贝,具体流程如下:- 第一次数据拷贝:当用户进程发起 read() 调用后,上下文从用户态切换至内核态。DMA(Direct Memory Access) 引擎从文件中读取数据,并存储到 Page Cache (内核态缓冲区)。- 第二次数据拷贝:请求的数据从内核态缓冲区拷贝到用户态缓冲区,然后返回给用户进程。同时会导致上下文从内核态再次切换到用户态。- 第三次数据拷贝:用户进程调用 send() 方法期望将数据发送到网络中,此时用户态会再次切换到内核态,请求的数据从用户态缓冲区被拷贝到 Socket 缓冲区。- 第四次数据拷贝:send() 系统调用结束返回给用户进程,再次发生上下文切换。此次操作会异步执行,从 Socket 缓冲区拷贝到 NIC 网络接口控制器的缓冲区。
页映射
NIC 网卡缓冲区
磁盘
DMA Copy
用户进程
文件描述符和buffer 长度
内核态
用户缓冲区
CPU Copy
sendfile
不使用零拷贝技术如下图
用户缓冲区
总结一下:- 传统 IO 执行的话需要 4 次上下文切换(用户态 -> 内核态 -> 用户态 -> 内核态 -> 用户态)和 4 次拷贝(磁盘文件 DMA 拷贝到内核缓冲区,内核缓冲区 CPU 拷贝到用户缓冲区,用户缓冲区 CPU 拷贝到 Socket 缓冲区,Socket 缓冲区 DMA 拷贝到协议引擎)。- mmap 将磁盘文件映射到内存,支持读和写,对内存的操作会反映在磁盘文件上,适合小数据量读写,需要 4 次上下文切换(用户态 -> 内核态 -> 用户态 -> 内核态 -> 用户态)和 3 次拷贝(磁盘文件 DMA 拷贝到内核缓冲区,内核缓冲区 CPU 拷贝到 Socket 缓冲区,Socket 缓冲区 DMA 拷贝到协议引擎)。- sendfile 是将读到内核空间的数据转到 Socket Buffer,进行网络发送,适合大文件传输,只需要 2 次上下文切换(用户态 -> 内核态 -> 用户态)和 2 次拷贝(磁盘文件 DMA 拷贝到内核缓冲区,内核缓冲区 DMA 拷贝到协议引擎)。
使用零拷贝技术如下图
Socket 缓冲区
DMA Copy
mmap 和 sendfile 都是零 Copy 的实现方案,只不过不同的场景使用不同的方案。mmap(Memory Mapped Files)其实就是把物理上的磁盘文件的地址和 Page Cache 地址进行映射,也称内存映射文件,完成映射后你对物理内存的操作会被同步到硬盘上(操作系统会在适当的时候执行)。简单的描述其作用就是:将磁盘文件映射到内存,用户通过修改内存就能修改磁盘文件。sendfile 是将读到内核空间的数据,转到 Socket Buffer,进行网络发送,相比较上面的 mmap 又节省了一次 CPU copy。mmap 和 sendfile 总结:- 都是 Linux 内核提供实现零拷贝的 API。- mmap 将磁盘文件映射到内存,支持读和写,对内存的操作会反映在磁盘文件上。- sendfile 是将读到内核空间的数据,转到 Socket Buffer,进行网络发送。
0 条评论
回复 删除
下一页