零拷贝技术
零拷贝技术
传统的I/O问题:
原理:

磁盘数据-->内核内存-->用户空间-->进程内存-->网卡
- 系统调用 read() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 执行拷贝,把文件数据从硬盘读到一个 kernel buffer 里
- 数据从 kernel buffer 拷贝到 user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode
- 系统调用 write() 产生一个上下文切换:从 user mode 切换到 kernel mode, 然后把步骤2读到user buffer 的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer和 socket 相关联
- 系统调用 write() 返回,产生一个上下文切换:从 kernel mode 切换到 user mode(第4次切换),然后DMA从 kernel buffer 拷贝数据到协议栈(第4次拷贝)
零拷贝介绍:
零拷贝就是上述问题的一个解决方案,通过尽量避免拷贝操作来缓解CPU的压力。零拷贝并没有真正做到“0”拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化
零拷贝页相关技术
MMAP ( Memory Mapping ):
原理:
磁盘数据-->内核-->映射内存
- 数据被读取到内核缓存,把这些内核缓存与进程缓存做内存映射,用户态程序指针到内核,直接用内核的缓存

详细解读:
- mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问
- mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系
- 实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享
- 内存映射减少数据在用户空间和内核空间之间的拷贝操作,适合大量数据传输
sendfile(旧版本):
原理:

磁盘数据--内核-->socket-->网卡
- 系统调用sendfile()通过DMA把硬盘数据拷贝到kernel buffer,然后数据被kernel 直接拷贝到另外一个与socket相关的 kernel buffer, 最后把socket缓存区中的数据拷贝的协议引擎中(网卡)
- 这里没有user mode和kernel mode 之间的切换,在kernel中直接完成了从一个 buffer 到另一个buffer的拷贝
DMA辅助的sendfile(新版本):
原理:

磁盘数据-->内核-->网卡
- 数据读取到内核中,只将记录数据位置和长度相关的数据保存到socket(也就是存索引信息),然后把数据从内核直接拷贝到协议引擎
注意: 需要硬件支持该功能才行,可以加速数据复制到内核、内核缓存到网络发送

浙公网安备 33010602011771号