1. 课程导论:网卡驱动与协议栈的关系
1.1 网卡驱动与协议栈的协作模型
在 Linux 网络子系统中,网卡驱动与协议栈通过 sk_buff(套接字缓冲区)结构体进行数据交换。驱动负责物理层与数据链路层的收发,协议栈负责网络层及以上的封装、路由与调度。两者之间通过 net_device 结构体进行抽象绑定,形成完整的发包/收包流水线。
核心概念:网卡驱动是协议栈与物理硬件之间的桥梁,sk_buff 是贯穿整个流程的数据载体。
1.2 数据包从应用到网线的完整旅程
一次典型的网络发包流程,从用户态应用程序调用 send() 开始,到数据帧从网卡物理端口发出为止,共经历 7 个关键阶段:
| 阶段 | 所在层级 | 核心函数/机制 | 关键数据结构 |
|---|---|---|---|
| 1. 系统调用 | 应用层 → 内核 | __sys_sendto() |
struct msghdr |
| 2. 传输层封装 | 协议栈 | tcp_sendmsg() / udp_sendmsg() |
struct sk_buff |
| 3. 网络层路由 | 协议栈 | ip_output() / ip_finish_output() |
struct rtable |
| 4. 邻居解析 | 邻居子系统 | neigh_output() |
struct neighbour |
| 5. 队列调度 | 流量控制层 | dev_queue_xmit() → qdisc 入队 |
struct Qdisc |
| 6. 驱动发送 | 网卡驱动 | ndo_start_xmit() |
struct net_device |
| 7. 硬件发送 | 物理层 | DMA 传输 / MAC 发送 | TX 描述符环 |
关键路径:从
send() 到 ndo_start_xmit() 之间,sk_buff 会经历多次克隆、分片和排队。理解 sk_buff 的引用计数管理是避免内存泄漏的核心。
1.3 课程目标与前置知识
课程目标
- 理解 sk_buff 核心机制:掌握 sk_buff 的结构布局、头指针操作、数据克隆与共享、引用计数管理。
- 掌握协议栈发包路径:从
send()系统调用到ndo_start_xmit()的完整代码流程。 - 精通队列调度算法:深入分析 pfifo_fast、HTB、TBF、FQ_Codel 等 qdisc 的入队/出队逻辑。
- 驱动开发实战:编写或修改网卡驱动的
ndo_start_xmit()回调,处理 TX 完成中断与环形缓冲区。 - 性能调优:分析发包瓶颈,利用
perf、ftrace、tc等工具进行诊断与优化。
前置知识要求
| 知识领域 | 具体要求 | 推荐资料 |
|---|---|---|
| C 语言与内核编程 | 熟悉指针、链表、内存分配;了解内核模块编写 | 《Linux Device Drivers》第 1-3 章 |
| Linux 网络基础 | 理解 TCP/IP 协议栈分层;会用 socket API | 《TCP/IP Illustrated》Vol.1 |
| 内核数据结构 | 了解 list_head、hlist、rcu 等基础结构 | 内核源码 include/linux/list.h |
| 驱动开发入门 | 了解 pci_driver、net_device_ops 注册流程 | 内核源码 drivers/net/ethernet/ |
注意:本课程涉及大量内核源码分析,建议读者具备至少 6 个月以上的 Linux 内核编程经验。如果对
spin_lock / RCU 等同步机制不熟悉,建议先阅读《Linux 内核设计与实现》第 9-10 章。
1.4 课程章节概览
本课程共 30 章,分为 5 个模块:
| 模块 | 章节范围 | 核心内容 |
|---|---|---|
| 基础篇 | 第 1-6 章 | sk_buff 结构详解、协议栈发包路径、邻居子系统 |
| 队列调度篇 | 第 7-14 章 | qdisc 框架、pfifo_fast/HTB/TBF/FQ_Codel 源码分析 |
| 驱动开发篇 | 第 15-22 章 | ndo_start_xmit 实现、TX 环形缓冲区、NAPI 与中断 |
| 性能调优篇 | 第 23-27 章 | perf/ftrace 分析、零拷贝、XDP 发包、多队列优化 |
| 实战项目篇 | 第 28-30 章 | 自定义 qdisc 编写、网卡驱动移植、发包延迟优化实战 |
学习建议:每章都配有可运行的实验代码和
trace 脚本。建议在 qemu + buildroot 搭建的实验环境中动手验证,不要只看源码。
1.5 实验环境准备
本课程推荐使用以下环境进行实验:
- 内核版本:Linux 5.10 LTS(长期支持版,社区维护活跃)
- 发行版:Ubuntu 20.04 / 22.04 或 Debian 11
- 虚拟化:qemu 6.0+ + buildroot 2022.02(用于快速构建最小根文件系统)
- 工具链:gcc 9+、make、flex、bison、elfutils
- 调试工具:perf、ftrace、bpftrace、tc、ethtool
快速开始:使用
git clone https://github.com/torvalds/linux.git -b v5.10 获取内核源码,make defconfig && make -j$(nproc) 编译内核,然后通过 qemu 启动测试。
# 编译内核示例
$ cd linux-5.10
$ make defconfig
$ make -j$(nproc) bzImage
$ make modules
$ make modules_install
# 使用 qemu 启动
$ qemu-system-x86_64 \
-kernel arch/x86/boot/bzImage \
-initrd /path/to/initramfs.cpio.gz \
-append "console=ttyS0" \
-netdev user,id=net0 \
-device e1000,netdev=net0