零拷贝知识的学习

零拷贝

预备知识:

  1. Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级的 Ring 0 和 Ring 3
  2. 内核空间(Ring 0)具有最高权限,可以直接访问所有资源,而用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。
  3. CPU 上下文: 当前进程在 CPU 中寄存器和程序计数器的数据的保存和切换
  4. 用户态与内核态的上下文切换的上下文切换,需要耗费时间和资源,影响性能

传统数据传输

服务端传输文件导客户端:

因为用户空间没有权限操作磁盘或网卡,内核的权限最高,这些操作设备的过程都需要交由操作系统内核来完成,所以一般要通过内核去完成某些任务的时候,就需要使用操作系统提供的系统调用函数;
传统 I/O 的工作方式是,数据读取和写入是从用户空间到内核空间来回复制,而内核空间的数据是通过操作系统层面的 I/O 接口从磁盘读取或写入。

需要的系统调用:

read(file, tmp_buf, len);write(socket, tmp_buf, len);

两次系统调用,而实际数据的传输过程发生了四次上下文切换,而频繁的上下文切换回影响性能

  • 第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。
  • 第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数据了,这个拷贝到过程是由 CPU 完成的。
  • 第三次拷贝,把刚才拷贝到用户的缓冲区里的数据,再拷贝到内核的 socket 的缓冲区里,这个过程依然还是由 CPU 搬运的。
  • 第四次拷贝,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程又是由 DMA 搬运的。

零拷贝的实现


传统的数据传输,由于要经历多次的数据拷贝(用户态与内核态的上下文切换),影响性能; 因此,可以通过减少数据的拷贝,从而优化数据的传输过程.

mmap() + write()

redis 读写那么快的实现;

mmap() 通过直接将内核的缓冲区里的数据 映射 到用户空间,减少了一次内核态到用户态数据的拷贝

系统调用函数:

buf = mmap(file, len);write(sockfd, buf, len);

具体过程:

  • 应用进程调用了 mmap() 后,DMA 会把磁盘的数据拷贝到内核的缓冲区里。接着,应用进程跟操作系统内核「共享」这个缓冲区;

  • 应用进程再调用 write(),操作系统直接将内核缓冲区的数据拷贝到 socket 缓冲区中,这一切都发生在内核态,由 CPU 来搬运数据;

  • 最后,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程是由 DMA 搬运的。

一共两次系统调用、三次数据拷贝、四次上下文切换

sendfile()

kafka 消费者读取数据的实现

专门用于发送文件的系统调用函数 sendfile() ; 调用函数如下 :

// 前两个参数分别是目的端和源端的文件描述符,后面两个参数是源端的偏移量和复制数据的长度,返回值是实际复制数据的长度。
#include <sys/socket.h>ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

具体实现流程:

  • sendfile() 能够代替 read() 和 write() 调用, 减少一次系统调用
  • 能够直接将内核缓冲区的数据拷贝到 socket 缓冲区, 减少了数据的拷贝次数

一共一次系统调用、三次数据拷贝、两次上下文切换

进一步,如果网卡支持 SG-DMA 技术, 那么数据传输的过程可以优化为如下所示:

  • 第一步,通过 DMA 将磁盘上的数据拷贝到内核缓冲区里;

  • 第二步,缓冲区描述符和数据长度传到 socket 缓冲区,这样网卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷贝到网卡的缓冲区里,此过程不需要将数据从操作系统内核缓冲区拷贝到 socket 缓冲区中,这样就减少了一次数据拷贝;

真正的零拷贝, 全程没有通过 CPU 来搬运数据,所有的数据都是通过 DMA 来进行传输的。

一共一次系统调用、两次数据拷贝、两次上下文切换

总结


为了提高文件传输的性能,于是就出现了零拷贝技术,它通过一次系统调用(sendfile 方法)合并了磁盘读取与网络发送两个操作,降低了上下文切换次数。
另外,拷贝数据都是发生在内核中的,天然就降低了数据拷贝的次数。

参考:

https://blog.csdn.net/csdnsevenn/article/details/108786260

https://juejin.cn/post/6854573213452599310

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值