乐于分享
好东西不私藏

【从零开始撸内核驱动源码】:以ttyserial(串口驱动)为例,串联字符设备驱动基础知识点的学习计划

【从零开始撸内核驱动源码】:以ttyserial(串口驱动)为例,串联字符设备驱动基础知识点的学习计划

Hello,大家好,我是程序媛MM。

本文约1800字,今年没有回老家,年到今日也差不多过完了,极其放松和休闲的一个年,身心完全的放松了。今日开始逐步进入学习状态,之前正式驱动走读的帖子《【从零开始撸内核驱动源码】:ttynull驱动》 算是入门开始撸驱动源码了,接下来的计划是一步一步将字符设备驱动的基础知识点梳理完毕,看书厘清理论知识,实操出真知,强化知识点。本文整理出字符设备驱动的走读路线。

关注公众号, 即可获得与Linux相关的电子书籍以及常用开发工具,文末有文档清单。


之前走读的 ttynull 是最简单的tty驱动(仅实现空设备,无实际硬件交互),接下来的学习应该围绕 “从无硬件交互 –>有简单硬件交互 –>复杂 tty 子系统 –>通用字符设备–>其他核心驱动类型” 的逻辑展开,既延续 tty 子系统的知识,又逐步扩展到更通用的驱动开发能力。

ttynull 是纯软件模拟的空设备,而 ttyserial(串口驱动)是tty子系统中最经典、最基础的有实际硬件交互的驱动,完美衔接之前的学习进度, 我粗略ttyserial目录内容, 整理出如下学习计划:

第一步:先吃透tty子系统的“极简硬件驱动”—— tyserial


代码路径:drivers/tty/serial/8250

优先看最简化的串口驱动:8250_core.c(8250 是最经典的 UART 芯片,Linux 串口驱动的基石),先跳过复杂的平台适配,聚焦 8250_port.c 中 “端口初始化、数据收发、中断处理” 的核心逻辑。

8250_port.c是8250系列 UART(通用异步收发器)串口驱动的端口操作核心层,是连接上层 TTY 子系统与底层硬件 UART 的关键桥梁。核心作用是屏蔽不同型号 UART 硬件的差异,为上层提供统一的串口操作接口,同时实现对串口硬件的精细化管理与适配。

[1].向下适配:兼容不同架构(x86/ARM/PowerPC 等)、不同厂商(TI/Freescale/Exar 等)、不同规格(8250/16550A/16750/XR16850 等)的 UART 硬件,处理寄存器映射、字节序、硬件缺陷等差异;

[2].向上抽象:为内核 TTY 子系统、控制台、用户态应用提供标准化的串口操作能力(收发数据、中断处理、FIFO 管理、RS485 仿真等)。

学习重点:

对比 ttynull,理解 tty 驱动如何对接实际硬件寄存器(如数据寄存器 THR/RBR、控制寄存器 LCR、状态寄存器 LSR);

掌握 tty 驱动中 “线路规程(line discipline)” 与硬件驱动的交互(ttynull 几乎没用到,而串口驱动是核心场景);

理解 tty 子系统的核心结构体(struct tty_driver/struct tty_operations)在实际硬件驱动中的完整实现;

初步接触 中断处理(串口的收发中断是驱动中最基础的中断场景)。

第二步:扩展到通用字符设备驱动(脱离 tty 子系统)


tty 驱动本质是字符设备的 “特殊形态”,掌握通用字符设备驱动能理解驱动开发的通用框架,为后续学习块设备、PCI 驱动打基础:

代码路径:经典字符设备驱动:drivers/char/mem.c(/dev/mem/zero/null 等设备,和 ttynull 同源,但更通用);

学习重点:掌握字符设备的核心流程:cdev_init/cdev_add–>设备号申请–>file_operations 实现–>设备节点创建;

对比 tty 驱动的 tty_operations 和通用字符设备的 file_operations,理解两者的异同;

学习驱动中的内存管理(kmalloc/kfree、vmalloc)、并发控制(spinlock/mutex,串口驱动中已初步接触);

理解驱动与用户空间的交互(copy_to_user/copy_from_user)。

第三步:深入到 “带总线 / 平台适配” 的驱动


前面的驱动要么无硬件,要么是简单寄存器操作,接下来需要理解 Linux 驱动的 “设备模型” 核心 —— 总线、设备、驱动分离:

优先学 platform 驱动(最通用的平台设备驱动):

代码路径:drivers/tty/serial/8250/8250_of.c(基于 platform 总线的 8250 串口驱动);

学习重点:platform_device 结构体、设备树(Device Tree)与驱动的对接(of_match_table)、资源申请(request_mem_region/ioport_map);

可选学 PCI 驱动(PC 端最常见的总线驱动):

代码路径:drivers/tty/serial/8250/8250_pci.c;

学习重点:PCI 设备的枚举、BAR 空间映射、PCI 驱动的 probe/remove 流程。

第四步:进阶到更复杂的驱动场景(按需选择)


完成前三步后,应该差不多掌握了驱动开发的核心基础,接下来可根据方向深入:

中断与 DMA(硬件驱动核心):

代码路径:drivers/tty/serial/8250/8250_dma.c(串口 DMA 收发);

学习重点:中断顶半部 / 底半部(tasklet/workqueue)、DMA 通道申请与配置、中断共享。

学习技巧:

[1].对比学习:始终以 ttynull 为基准,对比后续驱动新增的逻辑(如硬件寄存器、中断、总线适配),明确 “新增代码解决了什么问题”;

[2].边看边搜:遇到不懂的结构体(如 struct uart_port),用 kernel-doc 查看内核注释(make kerneldocs 或在线查 kernel.org 文档);

[3].动手验证:可以在 qemu 中运行内核,通过 cat /proc/tty/drivers/ls /dev/ttyS* 观察串口驱动的加载,或修改简单驱动(如给 ttynull 加个打印)编译测试。

总结


我计划的学习路径核心是:ttynull–>ttyserial(8250)–>通用字符设备–>platform/PCI 驱动–>中断 / DMA / 块设备 / 网络设备,由 “无硬件” 到 “有硬件”、由 “单功能” 到 “完整设备模型” 逐步深入;

重点掌握 tty 子系统与通用字符设备的衔接、硬件寄存器操作、中断处理、Linux 设备模型(总线 / 设备 / 驱动分离)这四大核心;

以 8250 串口驱动为核心案例,它几乎涵盖了字符设备驱动的所有基础知识点,是入门的最佳范本。

以上为全文内容。

往期文章(欢迎订阅技术分享栏目全部文章):

从零开始撸内核驱动源码:新手入门指南
Linux内核驱动源码走读之编译内核及外部驱动实操指南
Linux内核驱动安装失败问题调试及解决方法
【精读】: 《Linux设备驱动程序》第三章–字符设备驱动程序
【精读】:《Linux设备驱动程序》第六章–高级字符驱动程序

谢谢你看到这里

这里是女程序员的笔记本

 15年+嵌入式软件工程师兼二胎宝妈

分享读书心得、工作经验,自我成长和生活方式。

希望我的文字能对你有所帮助

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 【从零开始撸内核驱动源码】:以ttyserial(串口驱动)为例,串联字符设备驱动基础知识点的学习计划

评论 抢沙发

6 + 6 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮