1. Linux内核与网络子系统概述

本章作为《Linux网卡驱动开发65讲实战》的开篇,旨在为读者建立宏观的知识框架。我们将从Linux内核的整体架构出发,逐步聚焦到网络子系统,最终明确网卡驱动在内核中的具体位置与作用。理解这一脉络,是后续深入开发网卡驱动的基础。

1.1 Linux内核架构简介

Linux内核是一个宏内核(Monolithic Kernel),但通过模块化设计实现了良好的扩展性与可维护性。其核心组件围绕进程管理、内存管理、文件系统、设备驱动和网络协议栈五大子系统展开。

下图展示了Linux内核的核心组件及其相互关系:

Linux 内核核心架构 用户空间 (User Space) — 系统调用接口 (System Call Interface) 进程管理 调度器 / IPC 内存管理 MMU / 页分配 文件系统 VFS / 具体FS 设备驱动 字符/块/网络 网络协议栈 (Network Stack) 套接字 / TCP/IP / 网络设备层 硬件抽象层 (HAL) / 中断处理 / DMA 硬件 (CPU / 内存 / 网卡 / 总线) 说明:网络子系统是内核中唯一同时涉及进程管理、内存管理、文件系统和设备驱动的交叉领域。 网卡驱动位于“设备驱动”与“网络协议栈”的交汇处,是数据进出系统的物理门户。
关键认知:Linux内核虽然庞大,但各子系统通过清晰的数据结构和接口协作。网卡驱动开发主要涉及设备驱动和网络协议栈两个子系统,同时需要理解内存管理(DMA缓冲区)和中断处理机制。

1.2 网络子系统分层模型

Linux网络子系统采用严格的层次化设计,从用户态应用程序到物理网卡,数据包依次经过以下核心层次:

层次 核心组件 主要职责 关键数据结构
系统调用层 socket() / bind() / sendmsg() 提供用户态网络编程接口 struct socket
套接字层 AF_INET / AF_PACKET 协议族抽象,管理套接字状态 struct sock
传输层 TCP / UDP 协议实现 端到端可靠传输或数据报服务 struct tcp_sock / struct udp_sock
网络层 IPv4 / IPv6 / ARP 路由选择、分片与重组 struct sk_buff
邻居子系统 ARP / ND 缓存 IP 地址到 MAC 地址的解析 struct neighbour
网络设备层 dev_queue_xmit() / netif_rx() 统一设备接口,流量控制与队列管理 struct net_device
网卡驱动层 ndo_start_xmit() / 中断处理 硬件寄存器操作、DMA传输、中断响应 struct net_device_ops

数据包在协议栈中的流动路径如下:

网络子系统分层模型与数据包路径 发送路径 (Tx) 接收路径 (Rx) 系统调用层 (System Call Interface) 套接字层 (Socket Layer) 传输层 (TCP / UDP) 网络层 (IPv4 / IPv6 / ARP) 网络设备层 (Net Device Layer) 网卡驱动层 (NIC Driver) 核心数据结构 struct sk_buff 贯穿整个协议栈,是数据包在内核中的唯一载体。
开发要点:网卡驱动开发者最常打交道的两个层次是网络设备层和网卡驱动层。你需要实现 struct net_device_ops 中的回调函数(如 ndo_start_xmit),并正确处理中断与NAPI收包流程。

1.3 网卡驱动在内核中的位置

网卡驱动位于内核设备驱动子系统的网络分支中,具体归属于 drivers/net/ethernet/ 目录。它在内核源码树中的位置如下:

linux/
├── drivers/
│   ├── net/
│   │   ├── ethernet/          # 以太网卡驱动(主要战场)
│   │   │   ├── intel/         # Intel 系列网卡驱动
│   │   │   ├── broadcom/      # Broadcom 网卡驱动
│   │   │   ├── realtek/       # Realtek 网卡驱动
│   │   │   └── ...            # 其他厂商驱动
│   │   ├── phy/               # PHY 芯片驱动
│   │   ├── usb/               # USB 网卡驱动
│   │   └── wireless/          # 无线网卡驱动
│   └── ...                    # 其他子系统驱动
├── include/
│   ├── linux/
│   │   ├── netdevice.h        # struct net_device 定义
│   │   ├── skbuff.h           # struct sk_buff 定义
│   │   └── etherdevice.h      # 以太网相关辅助函数
│   └── net/                   # 网络协议栈头文件
└── net/
    ├── core/                  # 网络核心层(dev.c, dev_addr_lists.c 等)
    ├── ipv4/                  # IPv4 协议实现
    └── ...                    # 其他协议

网卡驱动在内核中的角色可以概括为以下三个核心职责:

  1. 硬件抽象:将物理网卡的寄存器、DMA引擎、中断控制器等硬件细节封装为内核可调用的标准接口。
  2. 数据通道:实现数据包从内核协议栈到网卡硬件(发送),以及从网卡硬件到内核协议栈(接收)的完整传输路径。
  3. 控制通道:处理网卡配置(MAC地址、MTU、流控、多队列等)、统计信息收集、电源管理等控制操作。
常见误区:初学者常将网卡驱动与网络协议栈混淆。网卡驱动不实现TCP/IP协议,它只负责将已经封装好的数据帧(sk_buff)通过DMA写入网卡发送缓冲区,或从网卡接收缓冲区读取数据帧提交给协议栈。协议解析是上层的工作。

下表总结了网卡驱动与内核其他模块的接口关系:

交互对象 接口/机制 驱动职责
网络设备层 struct net_device_ops 实现 open/stop/start_xmit/change_mtu 等回调
中断子系统 request_irq() / NAPI 注册中断处理函数,实现轮询收包
内存管理 DMA API (dma_alloc_coherent) 分配DMA缓冲区,管理描述符环
PCI/平台总线 struct pci_driver 设备探测、资源分配、电源管理
用户空间 ioctl / ethtool / sysfs 提供设备信息查询与配置接口