温馨提示×

Linux驱动怎么入门

小樊
86
2026-07-22 03:31:11
栏目: 智能运维

入门 Linux 驱动开发确实有个陡峭的学习曲线,但路线很清晰:C 语言基础 → Linux 内核基础 → 字符设备驱动 → 进阶

这是一份针对性很强的入门指南,包含了学习路线、核心概念、推荐书籍和实践建议


第一阶段:知识储备(磨刀不误砍柴工)

在写驱动之前,你必须掌握以下内容:

  1. C 语言(精通)
    • 重点:指针、结构体、内存操作(malloc/free 对应内核里的 kmalloc/kfree)、链表操作(内核大量使用链表)。
  2. 微机原理 / 计算机体系结构
    • 理解什么是 CPU特权级(用户态 vs 内核态)。
    • 理解 内存地址(物理地址、虚拟地址、MMU)。
    • 理解 中断(Interrupt)DMA
  3. 简单的硬件知识
    • 知道寄存器(Register)是什么。
    • 知道 GPIO、I2C、SPI 等常见总线的基本概念(不需要会画电路图,但要懂协议)。

第二阶段:环境搭建(不要在真机上乱搞)

强烈建议:使用虚拟机 + Linux 虚拟机 + QEMU/开发板进行学习。

  1. 宿主机:Windows 或 Mac。
  2. 虚拟机:安装 Ubuntu(20.04 或 22.04 均可)。
  3. 内核源码
    • 在 Ubuntu 上安装内核源码:sudo apt-get install linux-source
    • 或者去 kernel.org 下载你正在使用的内核版本的源码。
  4. 编辑器:VSCode(配合 C/C++ 插件和 compile_commands.json 看代码体验极佳)。

第三阶段:核心概念与第一个驱动(Hello World)

Linux 驱动主要分为三类:字符设备块设备网络设备。入门从**字符设备(Character Device)**开始,因为键盘、鼠标、串口、LED、各种传感器都属于这类。

1. 核心概念

  • 模块(Module):驱动是作为模块加载到内核中的。你可以动态加载(insmod)和卸载(rmmod),不需要每次都重启系统编译内核。
  • 用户态 vs 内核态:应用程序不能直接访问硬件,必须通过系统调用陷入内核,由驱动操作硬件。
  • 一切皆文件:驱动通常会在 /dev 目录下生成一个设备文件,应用程序通过 open, read, write, close 来操作它。

2. 第一个驱动:Hello World

创建一个 hello.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

// 模块加载时执行
static int __init hello_init(void) {
    printk(KERN_INFO "Hello, Linux Kernel!\n"); // 注意:内核里用 printk,不是 printf
    return 0; // 0 表示成功
}

// 模块卸载时执行
static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, Linux Kernel!\n");
}

module_init(hello_init); // 宏,指定入口
module_exit(hello_exit); // 宏,指定出口

MODULE_LICENSE("GPL"); // 必须声明许可证,否则内核会报污染警告
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A Simple Hello World Module");

3. Makefile

同目录下创建 Makefile

obj-m += hello.o

# 这里需要指向你的内核源码目录,如果是当前系统,通常是 /lib/modules/$(shell uname -r)/build
KDIR := /lib/modules/$(shell uname -r)/build

all:
	make -C $(KDIR) M=$(PWD) modules

clean:
	make -C $(KDIR) M=$(PWD) clean

4. 编译与运行

make
sudo insmod hello.ko      # 插入模块
dmesg | tail              # 查看内核日志,应该能看到 "Hello..."
sudo rmmod hello          # 移除模块(注意这里不要加 .ko)
dmesg | tail              # 应该能看到 "Goodbye..."
lsmod | grep hello        # 查看模块是否加载

第四阶段:深入字符设备驱动(关键步骤)

仅仅打印 Hello 是不够的,你需要学会如何操作硬件(模拟硬件)。你需要掌握以下 API:

  1. 注册设备号register_chrdev_regionalloc_chrdev_region
  2. cdev 结构体:这是字符设备的核心结构体。
  3. 文件操作结构体 file_operations
    • 你要实现 .open, .release, .read, .write 这些函数指针。
    • 当用户调用 read() 时,内核就会调用你写的 .read 函数。
  4. 自动创建设备节点(devnode):使用 class_createdevice_create,这样加载驱动后 /dev/ 下会自动出现设备文件,不用手动 mknod

推荐练习项目:

  • 虚拟字符设备:在内存里申请一块空间,模拟一个“设备”。实现 readwrite,把数据从用户态拷到内核态(copy_to_user, copy_from_user)。
  • LED 驱动:如果你有树莓派或任何开发板,这是最好的练手项目。

第五阶段:进阶与并发

当驱动稍微复杂一点,你必须考虑并发问题:

  • 并发与竞态:多个进程同时访问你的驱动怎么办?
  • 锁机制:自旋锁(Spinlock)、信号量(Semaphore)、互斥体(Mutex)。
  • 中断处理request_irq
  • 阻塞与非阻塞wait_queue

推荐学习资源(按优先级排序)

书籍(必读)

  1. 《Linux 设备驱动程序》(第三版,简称 LDD3)
    • 地位:圣经。
    • 注意:这本书基于 2.6 内核,代码不能直接在 5.x 或 6.x 的新内核上编译。但它讲内核机制和思想是完美的。你需要结合新内核源码去理解它的变化。
  2. 《精通 Linux 设备驱动程序开发》
    • 比较厚,内容比较全。
  3. 宋宝华《Linux 设备驱动开发详解》
    • 国内口碑很好,结合 ARM 和具体代码,适合国人阅读。

在线资源

  • Linux Kernel Documentation:内核源码里的 Documentation/ 目录是最好的手册。
  • 内核源码本身:看源码是最好的学习。从简单的驱动看起,比如 drivers/char/mem.c(内存设备驱动)。

视频课程

  • 网上有很多免费的入门视频(如韦东山、正点原子等),结合开发板演示,比看书直观。

总结学习路线图

  1. Day 1-3:搭建环境,编译内核,跑通 Hello World 模块。理解 insmodrmmod
  2. Week 1:手写一个无硬件操作的字符设备驱动。学会 file_operations,学会 copy_to_user
  3. Week 2:学习如何自动创建设备节点 (class_create)。
  4. Week 3:理解并发控制,在驱动里加入锁。
  5. Week 4:如果有硬件,点个灯;如果没有,写个虚拟的 FIFO 驱动。
  6. 后续:中断、定时器、I2C/SPI 子系统。

最重要的一点: Linux 驱动内核 API 变化很快。千万不要死记硬背代码,一定要学会查看当前内核版本的源码和头文件

0