操作系统IO过程与零拷贝

南桥中的DMA控制器是个什么东西?

我们曾经在硬件基础知识中讲过:CPU直接从磁盘/网卡中读/写取数据到内核(操作系统)缓冲区【磁盘高速缓存(PageCache)】会降低CPU效率,而这个工作CPU会交给南桥中的DMA控制器完成的。

当我们要将磁盘中的文件发送到互联网时,操作系统是怎么做的?

  • 我的程序很简单:两个系统调用:
syscall.Read(fd int, p []byte)
syscall.Write(fd int, p []byte)
  • 但这两个系统调用背后发生的事情却不简单:
    两个系统调用
    四次数据拷贝
    四次CPU用户态与内核态的上下文的切换
    在这里插入图片描述

四次数据拷贝

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

发现问题:

在数据传输的场景中,用户并不会对数据进行「再加工」,所以没必要将数据拷贝到用户缓冲区。针对这个问题,产生一种技术:零拷贝

零拷贝

零拷贝技术实现的方式通常有 2 种:

  • mmap + write
  • sendfile

mmap + write

系统调用:

syscall.Mmap(fd int, offset int64, length int, prot int, flags int)
syscall.Write(fd int, p []byte)

mmap() 系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间,这样,操作系统内核与用户空间就不需要再进行任何的数据拷贝操作。

在这里插入图片描述

具体过程如下:

  1. 应用进程调用了 mmap() 后,DMA 会把磁盘的数据拷贝到内核的缓冲区里。接着,应用进程跟操作系统内核「共享」这个缓冲区
  2. 应用进程再调用 write(),操作系统直接将内核缓冲区的数据拷贝到 socket 缓冲区中,这一切都发生在内核态,由 CPU 来搬运数据;
  3. 最后,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程是由 DMA 搬运的。

我们可以得知,通过使用 mmap() 来代替 read(), 可以减少一次数据拷贝的过程

sendfile

在 Linux 内核版本 2.1 中,提供了一个专门发送文件的系统调用函数 sendfile(),函数形式如下:

syscall.Sendfile(outfd int, infd int, offset *int64, count int)

从 Linux 内核 2.4 版本开始起,对于支持网卡支持 SG-DMA 技术的情况下, sendfile() 系统调用更高效了:

  1. 通过 DMA 将磁盘上的数据拷贝到内核缓冲区里;
  2. 缓冲区描述符和数据长度传到 socket 缓冲区,这样网卡的 SG-DMA 控制器可以直接将内核缓存中的数据拷贝到网卡的缓冲区里,此过程不需要将数据从操作系统内核缓冲区拷贝到 socket 缓冲区中,这样就减少了一次数据拷贝.
    在这里插入图片描述

零拷贝的应用

Kafka

Kafka 这个开源项目,就利用了「零拷贝」技术,从而大幅提升了 I/O 的吞吐率,这也是 Kafka 在处理海量数据为什么这么快的原因之一。

Nginx

Nginx 也支持零拷贝技术,一般默认是开启零拷贝技术,这样有利于提高文件传输的效率,是否开启零拷贝技术的配置如下:

http {
...
    sendfile on
...
}

延伸:零拷贝是基于 磁盘高速缓存(PageCache)

「内核缓冲区」实际上是磁盘高速缓存(PageCache)
PageCache 的优点主要是两个:

  • 缓存最近被访问的数据;
  • 预读功能;

Referen:https://zhuanlan.zhihu.com/p/258513662

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值