跳转到正文

程序怎样把数据交给网卡? ​

阶段 0 · 计算机与数据基础 · 第 2 课

你在电脑上同时打开了聊天软件和浏览器。当你在聊天框按下发送键,想把字母 A 发出去时,为什么聊天软件不能自己直接往网卡上写电信号?如果两个软件同时抢网卡,数据会不会撞成一团?

在第 1 课中,我们知道字母 A 在计算机里编码为一个字节(Byte) 01000001。这一课我们留在发送端主机内部,追踪这个字节如何从应用程序一路走到网卡硬件。

学完本课后,你将能够:

  1. 解释程序、进程、操作系统与驱动程序在发送数据时的分工。
  2. 定位一个待发送字节在用户空间内存、内核缓冲区和网卡硬件之间的搬运路径。
  3. 说出直接内存访问(DMA)与中断为什么能把 中央处理器(CPU) 从繁重的数据搬运中解放出来。

从用户空间的聊天进程内存,经系统调用进入内核空间的缓冲区,再由网卡驱动配合 DMA 交给网卡发送。

1. 先看图:三个区域各管什么? ​

上图把一台电脑的发送路径分成了三个区域:

  • ① 用户空间(应用程序):你运行的聊天软件、浏览器都在这里工作。它们只负责生成或展示业务数据(例如把字母 A 变成 01000001),不能直接碰触硬件。
  • ② 内核空间(操作系统与驱动):操作系统的核心区域。它替所有软件统一排队、按网络规则加上控制头,再通过网卡驱动程序指挥网卡。
  • ③ 硬件设备(网卡 NIC):真正的物理接口,负责把内存里的字节流变成网线上的电信号或光纤里的光脉冲。

2. 程序与进程:为什么软件之间不会串门? ​

躺在硬盘里的聊天软件可执行文件只是静态的代码,叫作程序(Program)。当你双击启动它,操作系统就会在内存(RAM)里为它分配一块独立的区域,并让 中央处理器(CPU) 执行它的指令——这个正在运行的程序实例就是进程。

为什么聊天软件不会读到或改掉浏览器里的网页密码?因为操作系统实施了内存隔离:

  1. 每个进程都以为自己独占了一片连续的内存(虚拟内存),聊天软件把 01000001 放在自己的用户态内存里。
  2. 进程运行在受限的用户态(User Mode),没有权限直接读写其他进程的内存,也没有权限直接向网卡寄存器下达硬件指令。
  3. 当聊天进程想要联网发送 01000001 时,必须向操作系统发起一次系统调用(例如调用发送接口 send 或 write),请求内核代为发送。

3. 跟着数据走:从用户内存到网卡队列 ​

我们先预测一下:如果聊天软件一秒钟产生 1000 条消息,而网卡由于链路繁忙暂时没发完,多出来的数据放在哪?答案是内存里的缓冲区。

让我们跟着 01000001 走完主机内部的四步交接:

步骤当前数据是什么存放在哪里谁在操作依据什么决定下一步
① 准备应用数据1 字节应用数据 01000001聊天进程的用户空间内存聊天进程(CPU 用户态)用户点击“发送”,发起系统调用
② 拷入内核并封装附加上各层协议控制头的数据包操作系统内核发送缓冲区操作系统内核网络栈(CPU 内核态)查找本机路由与接口,决定从哪张网卡发出
③ 挂载发送队列完整的待发以太网帧字节序列内存中的网卡发送环形队列(TX Ring)网卡驱动程序填写描述符(内存地址与长度),通知网卡取数据
④ 硬件读取并发送二进制比特流 → 物理信号网卡内部缓存 → 物理网线网卡(NIC)(DMA + MAC + PHY)按描述符地址读取内存,校验并编码上线

课后巩固 · 练习 · 单选

电脑上同时开着浏览器和聊天软件,为什么聊天软件不能直接篡改浏览器内存里的网页数据,也不能绕过系统独占网卡?

4. CPU、内存与网卡怎样高效配合? ​

如果每发一个字节,都要让 中央处理器(CPU) 亲自从内存(RAM)里读出来、再塞进网卡,那么在千兆(每秒约 1.25 亿字节)或万兆网络下,CPU 光搬运数据就会忙得不可开交。

现代计算机用 直接内存访问(DMA) + 中断 解决了这个问题:

CPU 填写发送描述符后,网卡通过 DMA 直接从内存读取待发帧,完成后用中断通知 CPU。

  1. 驱动填单(描述符):CPU 执行网卡驱动程序代码,在内存队列里写下一张“提货单”(描述符),标明:“待发送的帧在内存地址 0x...,长度多少字节”,然后敲一下网卡的门铃寄存器。
  2. 网卡自己提货(DMA):网卡里的 直接内存访问(DMA) 引擎直接通过主板总线(如 PCIe)去内存读取这帧数据,交给 MAC 和 PHY 发送上网线。这期间 CPU 可以转身去处理别的程序。
  3. 干完活汇报(中断):网卡把一批帧发送完毕(或者从网线上收到了新帧并写入内存)后,向 CPU 发出一个硬件中断。CPU 收到通知后,再去清理已发送的缓冲区或把新收到的数据交给对应进程。

从模型到真实系统: 上述模型假设只有单队列中断。在真实的高负载 Linux 服务器上,为了防止每秒几十万次中断打断 CPU,网卡驱动还会启用 NAPI(轮询合并) 和 多队列 RSS,把一次中断变成批量收取多帧。

课后巩固 · 练习 · 单选

在现代千兆或万兆网卡发送数据时,为了避免 CPU 逐字节把数据从内存搬到网卡,硬件采用了什么机制?

5. 小结与下一步 ​

现在,发送端已经能把一串字节顺利推上网线了。但如果两台电脑直接用一根网线连起来,接收端收到一长串 0 和 1 时,怎样知道哪几个字节是文件名、哪几个字节是文件内容?下一课我们来看为什么两台电脑交换数据必须设计协议。