当前位置:首页 > 系统教程 > 正文

Linux Kernel 4.9.88 UART子系统深度解析核心结构体与分层设计思想完全指南

Linux Kernel 4.9.88 UART子系统深度解析核心结构体与分层设计思想完全指南

你是否曾被Linux内核中复杂的UART驱动代码困扰? 本文将带你以Linux 4.9.88 LTS版本为蓝本,零基础拆解UART子系统的骨架——从最核心的uart_driveruart_port到硬件操作函数集,彻底理清串口驱动的工作奥秘。无需底层专家,看完你也能修改UART驱动!

Linux Kernel 4.9.88 UART子系统深度解析核心结构体与分层设计思想完全指南 UART子系统 Linux内核4.9.88 uart_driver结构体 uart_port结构体 第1张

▲ UART子系统分层架构及核心结构体关系(图片示意)

一、为什么你需要理解UART子系统?

UART(通用异步收发传输器)是嵌入式Linux中最常用的低速通信接口。在Linux内核4.9.88中,UART子系统已经高度抽象,向上对接tty层,向下通过uart_driver结构体uart_port结构体分离“驱动逻辑”与“硬件描述”。掌握这些结构体,你就能轻松为新的串口芯片编写驱动,或者理解现有驱动(如8250、pl011)的运行机制。

二、UART子系统整体设计——分层与协作

整个子系统分为四层:tty核心层(提供/dev/tty*接口)、线路规程(数据加工)、UART核心层(通用逻辑,位于drivers/tty/serial/serial_core.c)和硬件驱动层(具体芯片操作)。4.9.88版本中,UART核心通过uart_driver注册自己,每个物理端口对应一个uart_port,而硬件的具体收发、中断控制则由uart_ops回调实现。

2.1 核心结构体之一:uart_driver

struct uart_driver是UART驱动的“身份证”,定义在#include 。它包含了tty_driver指针、设备号、驱动名称、端口表等。当你调用uart_register_driver()时,内核会分配tty驱动并关联。关键成员如下:

  • struct module *owner —— 通常为THIS_MODULE,管理模块引用计数
  • const char *driver_name —— 驱动名称,显示在/proc/tty/drivers
  • struct uart_port * *ports —— 保存该驱动管理的所有uart_port指针数组
  • struct tty_driver *tty_driver —— 底层tty驱动,UART核心帮你填充

2.2 核心结构体之二:uart_port

uart_port是UART子系统中最庞大的结构体(超过60个字段),它描述了一个独立串口端口的全部属性。在4.9.88中,它包含了I/O基地址、中断号、波特率、FIFO大小、串口类型(PORT_*)、以及指向uart_ops的指针。注意:port->ops就是硬件驱动提供给你的“开关函数”。

  • unsigned long mapbase —— 物理内存基地址
  • unsigned int irq —— 中断号
  • struct uart_ops *ops —— 硬件操作函数表(重中之重)
  • unsigned int fifosize —— 硬件发送FIFO深度,用于流控
  • struct device *dev —— 关联的设备结构体(设备模型)

2.3 核心结构体之三:uart_ops

这是驱动开发者必须实现的一组回调。每个函数都操作具体的uart_port硬件。uart_ops直接决定了串口是否能收发数据。例如:

回调函数 作用说明
startup 申请中断、初始化FIFO、使能收发
shutdown 释放中断、关闭端口
set_termios 设置波特率、数据位、停止位、校验
tx_empty 检查发送FIFO是否空
put_char 单字符发送(轮询模式)
start_tx 使能发送中断,触发发送

三、Linux 4.9.88中的设计演进与细节

Linux内核4.9.88中,UART子系统引入了一些优化:比如uart_port中增加了attr_group用于设备属性,更好地支持sysfs;同时中断处理统一使用threaded irq机制(可选)。但核心思想没有变化——仍然是“uart_driver + uart_port + uart_ops”三驾马车。了解这个版本,你就可以向下兼容3.x,向上理解5.x。

🔧 实战小贴士:如何快速找到对应结构体的定义?

在4.9.88源码根目录,使用grep "struct uart_driver" . -R --include="*.h",你会发现在include/linux/serial_core.h中。同样,uart_port结构体也在同一个文件中。这是所有串口驱动的心脏。

四、从零构建UART驱动:核心步骤

为了让你更直观地理解这些结构体如何协同,我们模拟一个最简单的虚拟UART驱动编写流程:

  1. 1 分配并初始化struct uart_driver,设置驱动名、设备号、端口数量。
  2. 2 实现struct uart_ops中的所有必要回调(至少包括startup、shutdown、set_termios、start_tx)。
  3. 3 定义struct uart_port实例,填充I/O资源、irq、ops指针,并调用uart_add_one_port()注册到uart_driver。
  4. 4 在模块入口注册uart_driver,出口注销。一切就绪!

五、总结:一张图记住UART子系统

💡 UART子系统的本质是:uart_driver提供骨架,uart_port描述个体,uart_ops注入灵魂。在Linux内核4.9.88中,这套设计经历了十余年考验,清晰、稳定、可扩展。掌握了uart_driver结构体uart_port结构体,你就能驾驭任何串口硬件。

原文链接:深入UART核心 —— 基于4.9.88 LTS版本解析 更新于:2026年2月12日