网卡
网卡如下 :
想起网卡就想起了零拷贝 , 软件开发中常常遇到 ,例如 MQ 中 ,例如 Nginx 中 .
首先,什么是“零拷贝”?
“零拷贝”的目标,顾名思义,就是尽量减少甚至完全避免数据在内存中的不必要的复制次数。
在传统的数据传输(比如从硬盘读取文件并通过网络发送)中,数据需要经历多次复制和上下文切换:
- 从硬盘到内核缓冲区:操作系统从硬盘读取文件数据,复制到内核空间的页面缓存。
- 从内核缓冲区到用户缓冲区:应用程序(例如一个Web服务器)需要处理这些数据,于是数据被从内核空间复制到用户空间的应用程序缓冲区。
- 从用户缓冲区到内核Socket缓冲区:应用程序准备发送数据,数据又被复制回内核空间的Socket缓冲区。
- 从Socket缓冲区到网卡:最后,数据从Socket缓冲区复制到网卡,最终发送到网络。
在这个过程中,数据被复制了4次,用户态和内核态之间也发生了4次上下文切换,CPU需要亲自处理所有这些复制工作,开销巨大。
那么,“零拷贝”和“网卡”是如何结合的呢?
“零拷贝”技术通过以下方式,巧妙地利用了网卡和操作系统的能力,来绕过这些昂贵的复制操作:
关键机制:DMA 和 内存映射
-
DMA:
- 无论是传统方式还是零拷贝,数据从硬盘到内存,以及从内存到网卡的最后一步,通常都由一个叫 DMA 的硬件来负责。
- DMA允许硬盘、网卡等外设不经过CPU,直接与内存交换数据。这就已经把CPU从两次复制工作中解放出来了。
-
零拷贝的核心技术(如
sendfile
):- 操作系统提供了像
sendfile()
这样的系统调用。 - 当应用程序需要发送一个文件时,它调用
sendfile()
,告诉内核源文件(在硬盘)和目标Socket。 - 内核会进行如下优化:
- 内存映射:内核将存放文件数据的内核缓冲区与网卡的Socket缓冲区进行映射,让它们指向同一块物理内存。
- 直接传输:然后,内核直接指示网卡,从这块被映射的内存区域读取数据并发送。
- CPU不参与数据复制:在整个过程中,数据没有被复制到用户空间,也没有在内核空间内来回复制。CPU只需要下达指令,而无需亲自搬运数据。
- 操作系统提供了像
光猫
互联网 <--(光信号)--> 光纤 <--(光信号)--> 光猫 <--(网络信号/网线)--> 路由器 <--(Wi-Fi/网线)--> 你的手机/电脑
入户光猫 , 光纤接在盒子后面 ,分出几个线口 ,有电视的 ,电话的, 网络的 .
交换机
路由器
在家里 ,接入光猫后的设备就是路由器
企业级的路由器又是长啥样的呢?
wifi 就是无线路由器 .