零拷贝

操作系统分为用户空间内核空间。程序处于用户空间,而磁盘属于硬件,操作系统本质上是程序和硬件设备的一个中间层。程序需要通过操作系统去调用硬件能力。
notion image
如果用户想要将数据从磁盘发送到网络。那么就会发生下面这几件事:程序会发起系统调用read(),尝试读取磁盘数据,
  • 磁盘数据从设备拷贝到内核空间的缓冲区。
  • 再从内核空间的缓冲区拷贝到用户空间。
程序再发起系统调用write(),将读到的数据发到网络:
  • 数据从用户空间拷贝到 socket 发送缓冲区
  • 再从 socket 发送缓冲区拷贝到网卡。
最终数据就会经过网络到达消费者。
notion image
整个过程,本机内发生了 2 次系统调用,对应 4 次用户空间和内核空间的切换,以及 4 次数据拷贝
notion image
一顿操作猛如虎,结果就是同样一份数据来回拷贝。有没有办法优化呢?有,它就是零拷贝技术,常见的方案有两种,分别是 mmap 和 sendfile。我们来看下它们是什么。

mmap 是什么

mmap 是操作系统内核提供的一个方法,可以将内核空间的缓冲区映射到用户空间。
notion image
用了它,整个发送流程就有了一些变化。程序发起系统调用mmap(),尝试读取磁盘数据,具体情况如下:
  • 磁盘数据从设备拷贝到内核空间的缓冲区。
  • 内核空间的缓冲区映射到用户空间,这里不需要拷贝。
程序再发起系统调用write(),将读到的数据发到网络:
  • 数据从内核空间缓冲区拷贝到 socket 发送缓冲区。
  • 再从 socket 发送缓冲区拷贝到网卡。
notion image
整个过程,发生了 2 次系统调用,对应 4 次用户空间和内核空间的切换,以及 3 次数据拷贝,对比之前,省下一次内核空间到用户空间的拷贝。
notion image
看到这里大家估计也蒙了,不是说零拷贝吗?怎么还有 3 次拷贝。mmap 作为一种零拷贝技术,指的是用户空间到内核空间这个过程不需要拷贝,而不是指数据从磁盘到发送到网卡这个过程零拷贝。
notion image
确实省了一点,但不多。有没有更彻底的零拷贝?有,用 sendfile.

sendfile 是什么

sendfile,也是内核提供的一个方法,从名字可以看出,就是用来发送文件数据的。程序发起系统调用sendfile(),内核会尝试读取磁盘数据然后发送,具体情况如下:
  • 磁盘数据从设备拷贝到内核空间的缓冲区。
  • 内核空间缓冲区里的数据可以直接拷贝到网卡。
notion image
整个过程,发生了 1 次系统调用,对应 2 次用户空间和内核空间的切换,以及 2 次数据拷贝。这时候问题很多的小明就有意见了,说好的拷贝怎么还有 2 次拷贝?
notion image
其实,这里的零拷贝指的是零 CPU拷贝。也就是说 sendfile 场景下,需要的两次拷贝,都不是 CPU 直接参与的拷贝,而是其他硬件设备技术做的拷贝,不耽误我们 CPU 跑程序。
Loading...
目录
文章列表
王小扬博客
产品
Think
Git
软件开发
计算机网络
CI
DB
设计
缓存
Docker
Node
操作系统
Java
大前端
Nestjs
其他
PHP