1. Linux网络子系统概述
Linux 网络子系统是内核中规模最大、耦合最紧密的模块之一,它向上为应用层提供 Socket 接口,向下通过网络设备驱动与物理硬件交互。理解其整体架构、设备模型以及驱动与协议栈的协作关系,是开发高性能网络驱动的基石。
1.1 Linux 网络协议栈架构
Linux 网络协议栈采用分层设计,每一层职责清晰,层与层之间通过标准化的数据结构(如 struct sk_buff)传递数据。下图展示了从用户态应用到底层硬件的完整数据流路径:
各层核心职责与关键数据结构如下表所示:
| 层级 | 核心职责 | 关键数据结构 / 函数 |
|---|---|---|
| 用户态 | 通过 Socket API 发起网络通信 | socket() / send() / recv() |
| 系统调用层 | 将用户态请求转换为内核态操作 | sys_sendmsg() / sys_recvmsg() |
| 协议无关层 | 提供统一的 Socket 操作接口,屏蔽协议差异 | struct proto / struct socket |
| 传输层 | 端到端可靠传输(TCP)或不可靠传输(UDP) | tcp_v4_rcv() / udp_rcv() |
| 网络层 | 路由选择、分片重组、IP 协议处理 | ip_rcv() / ip_output() |
| 邻居子系统 | IP 地址到链路层地址的解析与缓存 | struct neighbour / arp_process() |
| 网络设备层 | 统一抽象物理/虚拟网络设备,驱动接口 | struct net_device / dev_queue_xmit() |
关键理解:
struct sk_buff 是贯穿整个协议栈的核心数据结构,它携带数据包内容、协议头指针、设备信息和控制标志。驱动开发中,发送路径通过 dev_queue_xmit() 将 sk_buff 送入协议栈,接收路径通过 netif_rx() 或 NAPI 将 sk_buff 上交给协议栈。
1.2 网络设备模型
Linux 内核使用 struct net_device 统一表示所有网络设备,无论是物理网卡(如 Intel I350)、虚拟设备(如 VLAN、Bridge、TUN/TAP)还是回环设备(lo)。设备模型的核心是 设备注册、操作函数集 和 NAPI 机制。
struct net_device 包含的关键字段与操作函数集如下:
| 字段 / 操作 | 类型 | 说明 |
|---|---|---|
name |
char[] |
设备名称,如 eth0、lo、vlan100 |
flags |
unsigned int |
设备标志,如 IFF_UP、IFF_BROADCAST、IFF_MULTICAST |
mtu |
unsigned int |
最大传输单元,默认 1500 字节 |
dev_addr |
unsigned char[] |
MAC 地址(6 字节) |
netdev_ops |
struct net_device_ops * |
驱动操作函数集,包含 open/stop/start_xmit 等 |
napi_list |
struct list_head |
NAPI 实例链表,用于轮询接收 |
priv |
void * |
驱动私有数据区域,通过 netdev_priv() 访问 |
驱动开发要点: 驱动必须实现
ndo_start_xmit 函数,该函数在协议栈调用 dev_queue_xmit() 时被触发,负责将 sk_buff 中的数据包发送到硬件。接收方向,驱动通过 NAPI 的 poll 回调从硬件读取数据包并构造 sk_buff 上交给协议栈。
1.3 驱动与协议栈的关系
网络设备驱动位于协议栈的最底层,是内核与硬件之间的桥梁。驱动不参与 TCP/IP 协议处理,只负责:
- 发送路径: 将协议栈下发的
sk_buff中的数据通过 DMA 写入硬件发送队列,并触发硬件发送。 - 接收路径: 从硬件接收队列读取数据,构造
sk_buff,通过 NAPI 或传统中断方式上交给协议栈。 - 控制路径: 处理设备打开/关闭、MTU 变更、多队列配置、流控等控制命令。
驱动与协议栈的交互通过以下核心接口完成:
| 方向 | 协议栈调用驱动 | 驱动调用协议栈 |
|---|---|---|
| 发送 | ndo_start_xmit(sk_buff, net_device) |
— |
| 接收(传统中断) | — | netif_rx(sk_buff) |
| 接收(NAPI) | poll(napi, budget) 由 NAPI 调度 |
napi_gro_receive() / netif_receive_skb() |
| 设备控制 | ndo_open() / ndo_stop() / ndo_change_mtu() |
netif_carrier_on() / netif_carrier_off() |
常见误区: 驱动开发者常误以为需要在驱动中处理 IP 分片或 TCP 校验和。实际上,协议栈会在
ndo_start_xmit 被调用前完成所有协议处理。驱动只需关注硬件描述符管理、DMA 映射和中断处理。现代网卡通常支持硬件校验和卸载(TSO/GSO/GRO),驱动应正确设置 net_device 的 features 标志以启用这些卸载功能。
1.4 本章小结
Linux 网络子系统采用清晰的分层架构,驱动位于最底层,通过 struct net_device 与协议栈交互。理解以下核心概念是后续章节的基础:
- 协议栈分层: 从 Socket 到设备层,每层职责明确,
sk_buff是贯穿全栈的数据载体。 - 设备模型:
net_device统一抽象所有网络设备,驱动通过net_device_ops提供操作函数。 - 驱动职责: 只负责数据搬运和硬件控制,不参与协议解析。发送调用
ndo_start_xmit,接收通过 NAPI 或netif_rx上交。 - NAPI 机制: 是现代高性能驱动的基础,将在后续章节深入讲解。