1. 课程导入

USB(Universal Serial Bus)自 1996 年问世以来,已成为嵌入式系统与 PC 外设最通用的连接标准。在 Linux 内核中,USB 子系统是一个高度分层、模块化的软件栈,其核心设计目标是:在保持主机-设备拓扑结构不变的前提下,为不同类别的设备提供统一的驱动接口。本章作为课程的开篇,将系统梳理 USB 协议栈的架构层次、主机控制器与设备的角色分工,并重点阐明 URB(USB Request Block) 在 USB 通信中的核心地位——它是驱动与硬件之间传递数据的最小工作单元,也是后续批量传输性能测试的基石。

💡 核心观点: 理解 URB 的生命周期管理,是优化批量传输吞吐量与延迟的关键。本章所有后续章节的性能测试方法,都建立在对 URB 提交、完成、重试机制的深刻理解之上。

1.1 USB 协议栈架构

Linux USB 子系统采用经典的 分层架构,从上到下依次为:USB 设备驱动层、USB 核心层(USBCore)、主机控制器驱动层(HCD),以及底层的 硬件主机控制器。每一层都封装了特定的职责,并通过标准接口与相邻层交互。

下面的 SVG 图展示了 USB 协议栈的完整分层结构,以及数据流在层与层之间的传递路径:

Linux USB 协议栈分层架构与数据流 用户空间应用程序 (libusb / sysfs / devfs) USB 设备驱动层 (usb_driver / probe / disconnect) USB 核心层 (USBCore: 设备枚举 / 带宽管理 / URB 路由) 主机控制器驱动层 (HCD: ehci-hcd / xhci-hcd / ohci-hcd) USB 主机控制器硬件 (EHCI / XHCI / OHCI / UHCI) 🔗 URB 贯穿全栈:从设备驱动提交,经 USBCore 路由,由 HCD 解析为硬件事务 批量传输、中断传输、等时传输、控制传输均以 URB 为基本载体

各层的主要职责与交互接口如下表所示:

层次 主要职责 关键数据结构 / 接口
用户空间 通过 libusb 或 sysfs 发起 I/O 请求,不直接接触内核 URB libusb_transfer → 内核 URB 转换
USB 设备驱动 实现具体设备协议(如存储、串口、HID),分配并提交 URB usb_fill_bulk_urb() / usb_submit_urb()
USB 核心层 管理设备枚举、配置选择、URB 路由、电源管理 struct usb_device / struct usb_host_endpoint
主机控制器驱动 将 URB 转换为硬件特定的 TD(Transfer Descriptor) struct urb → struct ehci_qtd / struct xhci_trb
硬件控制器 在 USB 总线上执行实际的数据包传输 寄存器级 DMA 操作 / 帧微帧调度
📌 开发提示: 在编写 USB 设备驱动时,你主要与 USB 设备驱动层 和 USB 核心层 打交道。URB 的分配、填充、提交和完成回调是驱动开发的核心循环。性能测试时,需要重点关注 HCD 层的调度延迟和硬件队列深度。

1.2 主机控制器与设备角色

USB 总线采用 主从式拓扑:主机(Host) 始终作为总线主控,负责发起所有事务;设备(Device) 只能被动响应主机的请求。这种设计简化了设备侧的硬件复杂度,但也将调度压力全部集中到了主机控制器上。

1.2.1 主机控制器的类型与演进

Linux 内核支持四种主流主机控制器规范,它们在寄存器接口、调度粒度和传输性能上存在显著差异:

规范 总线类型 速度支持 调度粒度 典型驱动
UHCI PCI USB 1.1 (Full/Low) 1 ms 帧 uhci-hcd
OHCI PCI / 嵌入式 USB 1.1 (Full/Low) 1 ms 帧 ohci-hcd
EHCI PCI USB 2.0 (High) 125 µs 微帧 ehci-hcd
XHCI PCI / ACPI USB 3.x (SuperSpeed+) 125 µs 微帧 + 流式传输 xhci-hcd

下面的 SVG 图展示了主机控制器与设备之间的角色关系,以及 URB 在其中的流动路径:

主机控制器与设备角色:URB 事务流 主机 (Host) USB 设备驱动 USBCore 路由 HCD (xhci-hcd) 主机控制器硬件 USB 总线 (Host ↔ Device) 设备 (Device) 设备功能逻辑 端点 (Endpoint) 设备控制器硬件 USB 收发器 (PHY) URB 在主机与设备之间传递数据
⚠️ 性能陷阱: 不同主机控制器对批量传输的调度策略差异巨大。例如,EHCI 使用周期性的微帧列表调度,而 XHCI 支持异步的流式传输(Streams),可以显著提高批量传输的并发度。在性能测试中,必须明确记录被测平台的主机控制器类型。

1.3 URB 在 USB 通信中的核心地位

URB(USB Request Block) 是 Linux USB 子系统中最核心的数据结构,定义在 <linux/usb.h> 中。它抽象了一次完整的 USB 数据传输请求,包含了从设备驱动到硬件控制器的所有必要信息。可以毫不夸张地说:USB 设备驱动的本质,就是 URB 的管理器。

1.3.1 URB 的关键字段

一个 URB 实例包含以下关键成员,它们直接决定了传输的行为和性能:

字段 类型 说明
dev struct usb_device * 目标 USB 设备
pipe unsigned int 端点管道信息(含方向、类型、端点号)
transfer_buffer void * 数据缓冲区指针(DMA 安全)
transfer_buffer_length int 缓冲区长度(字节)
transfer_flags unsigned int 传输标志(如 URB_NO_TRANSFER_DMA_MAP)
complete usb_complete_t 完成回调函数(在中断上下文或 tasklet 中执行)
context void * 回调上下文(通常指向驱动私有数据)
actual_length int 实际传输的字节数(在完成回调中读取)
status int 传输状态(0 表示成功,负值表示错误)
interval int 中断/等时传输的轮询间隔(毫秒或微帧)

1.3.2 URB 的生命周期

一个典型的 URB 从创建到销毁,经历以下阶段:

  1. 分配: 使用 usb_alloc_urb() 分配 URB 实例,传入 iso_packets 数量(非等时传输传 0)。
  2. 填充: 根据传输类型调用对应的填充函数:
    • usb_fill_control_urb() — 控制传输
    • usb_fill_bulk_urb() — 批量传输
    • usb_fill_int_urb() — 中断传输
    • 等时传输需要手动设置 urb->iso_frame_desc[]
  3. 提交: 调用 usb_submit_urb() 将 URB 交给 USBCore。此函数可能睡眠(GFP_KERNEL)或在原子上下文中调用(GFP_ATOMIC)。
  4. 调度与执行: USBCore 将 URB 路由到对应的 HCD,HCD 将其转换为硬件事务描述符,由主机控制器在总线上执行。
  5. 完成回调: 传输完成后(成功或失败),HCD 调用 URB 的 complete 回调函数。驱动在此回调中检查 urb->status 和 urb->actual_length。
  6. 回收: 驱动调用 usb_free_urb() 释放 URB 内存,或在完成回调中重用 URB(通过 usb_submit_urb() 再次提交)。

下面的 SVG 图展示了 URB 从分配到完成的完整生命周期,以及各阶段涉及的关键函数:

URB 生命周期:从分配到完成 ① 分配 usb_alloc_urb() ② 填充 usb_fill_bulk_urb() ③ 提交 usb_submit_urb() ④ 调度与执行 HCD → 硬件事务 ⑤ 完成回调 complete() 检查 status ⑥ 回收或重用 usb_free_urb() / 再次 usb_submit_urb() 💡 性能关键路径 ③→④→⑤ 的延迟决定吞吐量

1.3.3 URB 与批量传输的关系

在 USB 规范定义的四种传输类型中,批量传输(Bulk Transfer) 与 URB 的绑定最为紧密:

  • 批量传输特点: 非周期性、大块数据、硬件级错误重传(CRC 校验 + 自动重试)、无带宽保证。
  • URB 映射: 一个批量 URB 对应一次或多次批量事务(取决于端点支持的最大包大小)。驱动通过 usb_fill_bulk_urb() 设置端点、缓冲区和回调。
  • 性能关键指标:
    • URB 提交频率: 每秒提交的 URB 数量直接影响吞吐量。
    • URB 大小: 批量传输建议使用端点支持的最大包大小(USB 2.0 为 512 字节,USB 3.0 为 1024 字节)的整数倍。
    • URB 队列深度: 同时提交多个 URB 到同一个端点,可以充分利用硬件流水线。
🚀 性能测试前置知识: 本课程后续章节将围绕批量 URB 的提交模式展开性能测试。你将学习如何通过调整 URB 大小、队列深度、提交间隔和 DMA 映射策略,来测量并优化批量传输的吞吐量(MB/s)和延迟(μs)。理解 URB 的生命周期是这一切的基础。

1.4 本章小结

本章建立了 USB 子系统的基础认知框架:

  • 分层架构: 设备驱动 → USBCore → HCD → 硬件,每一层都有明确的职责边界。
  • 主从角色: 主机控制器始终是总线主控,设备被动响应;不同主机控制器(UHCI/OHCI/EHCI/XHCI)的调度机制影响传输性能。
  • URB 核心地位: URB 是 USB 通信的最小工作单元,其分配、填充、提交、完成回调、回收构成了驱动开发的主循环。批量传输的性能优化,本质上是对 URB 生命周期的精细控制。