直接上流程:
网卡 → DMA → RX队列 → 硬中断 → 软中断 → 协议栈 → Socket队列 → 唤醒进程 → 系统调用 → 拷贝到用户态 → 应用处理


1. 物理层 & 网卡硬件接收
- 网线 / 光纤传来电信号 / 光信号
- 网卡(NIC)将信号解码成以太网帧
- 网卡校验帧格式、CRC 校验
- 校验通过后,通过 DMA 把帧写入主机内存的环形缓冲区(RX Queue)
- 不会逐字节交给 CPU,直接内存写入,效率更高
2. 网卡触发硬件中断
- 网卡写入完成后,向 CPU 发送硬件中断(IRQ)
- 告诉 CPU:"有包到了,快来处理"
现代网卡支持 RSS(多队列),可以把不同流哈希到不同队列,绑定不同 CPU,避免单核瓶颈。
3. 内核硬中断处理(非常快)
内核中断处理程序做极简工作:
- 应答中断,让网卡继续收包
- 不做复杂协议处理
- 唤醒软中断(ksoftirqd) 去真正处理数据包
- 立即退出硬中断
目的:硬中断必须快,否则会阻塞其他硬件。
4. 内核软中断处理(真正收包逻辑)
内核线程 ksoftirqd 开始干活:
- 从内存 RX 队列取出以太网帧
- 剥离以太网头,判断是 IPv4/IPv6/ARP 等
- 交给 网络协议栈(netif_receive_skb)
5. 内核网络协议栈处理
① 网络层(IP 层)
- 解析 IP 头,校验
- 查路由表:判断是本机接收还是转发
- 如果是本机,根据协议字段交给:
- TCP → TCP 协议栈
- UDP → UDP 协议栈
- ICMP → ICMP 处理
② 传输层(TCP/UDP)
UDP 流程
- 校验 UDP 头
- 根据 目的端口 查找对应 socket
- 把数据放入 socket 的 接收队列(recv_queue)
TCP 流程更复杂
- 处理序列号、滑动窗口
- 做 ACK 回复、重传管理、拥塞控制
- 按流重组,保证有序
- 数据放入对应 socket 的接收队列
到此为止,所有工作都在内核态完成。
6. 唤醒等待的用户进程
- 当 socket 队列有数据时,内核会:
- 唤醒阻塞在
recv()/read()/epoll上的应用进程 - 把进程从睡眠态 变为就绪态,等待调度
- 唤醒阻塞在
7. 进程被调度,进入系统调用
应用进程被 CPU 调度后,执行:
read()recv()recvfrom()
这些都是系统调用 ,会从用户态 → 内核态。
8. 内核把数据拷贝到用户态缓冲区
- 内核从 socket 接收队列取出数据
- 将数据从 内核空间内存 → 拷贝到用户空间内存
- 拷贝完成,系统调用返回
这一步是传统网络最大开销之一:一次内存拷贝(用户态 / 内核态切换 + 数据复制)
9. 应用进程拿到数据,回到用户态执行
- 应用开始处理 HTTP/DNS/ 业务协议等
- 流程结束