第1章 Linux驱动开发的方式
- mmap映射型设计方法。【不推荐】
- 将芯片上的物理地址映射到用户空间的虚拟地址上,用户操作虚拟地址来操作硬件。
- 使用文件操作集(file_operatiopns)设计方法。【极致推荐】
- platfrom总线型设置方法。【比较流行】
- 设备树。【推荐】
第2章 Linux设备分类
2.1 字符设备
- LED
- 显卡
- 声卡
- USB
- 鼠标
- 键盘
- 触摸屏
2.1.1 字符设备特点
按字节流顺序访问
- 数据以字节为单位进行读写,像“流”一样,通常不支持随机访问。
- 例如:串口、键盘、鼠标、LED 驱动等。
不经过文件系统缓冲(可选)
- 可以直接进行
read()
、write()
系统调用,绕过内核页缓存(也可以使用缓存)。 - 支持非阻塞 I/O、异步 I/O。
- 可以直接进行
无固定块大小概念
- 传输单位是字节或任意大小的数据块,不像块设备固定为 512B 或 4KB。
设备文件通常位于
/dev
- 如
/dev/ttyS0
、/dev/leds
、/dev/mychardev
。 - 主设备号(major)标识设备类型,次设备号(minor)标识具体设备。
- 如
常见操作函数
open
,close
,read
,write
,ioctl
等。
不需要文件系统支持即可访问
- 可以直接通过系统调用操作设备文件
2.2 块设备
- 硬盘
- nand flash
- SD卡
- U盘
- eMMC卡
2.2.1 块设备特点
以“块”为单位进行数据传输
- 块大小通常是 512 字节、4KB 等,必须是 2 的幂。
- 所有 I/O 操作都对齐到块边界。
支持随机访问
- 可以直接读写任意一个数据块(如第 1000 个块),适合存储设备。
通过内核缓冲区(页缓存)进行 I/O
- 块设备 I/O 通常经过 Buffer Cache 或 Page Cache,提高性能。
- 支持写缓存、预读等优化。
通常用于存储系统
- 是文件系统(如 ext4、XFS)的底层载体。
I/O 请求被放入请求队列(request queue)
- 内核可以对请求进行合并、排序(电梯算法),提高效率。
设备文件在
/dev
下- 如
/dev/sda
、/dev/sda1
、/dev/mmcblk0
。
- 如
可被挂载为文件系统
- 例如:
mount /dev/sda1 /mnt
- 例如:
块设备驱动带有缓存。
2.3 网络设备
- 无线网卡
- 有线网卡
2.3.1 网络设备的特点
不支持文件操作接口
- 没有
open()
、read()
、write()
等系统调用。 - 不创建传统意义上的设备文件(如
/dev/eth0
不存在)。
- 没有
通过套接字(socket)接口访问
- 用户通过
socket()
、send()
、recv()
、ioctl()
等进行网络通信。
- 用户通过
数据以“包”(packet)为单位传输
- 面向数据包,不是字节流或块。
- 支持协议栈(如 TCP/IP)。
双向传输:发送和接收队列
- 有独立的发送队列(TX queue)和接收队列(RX queue)。
- 使用中断或 NAPI 处理数据包。
由内核网络子系统管理
- 属于
net_device
结构体管理,不是inode
。 - 通过
ifconfig
、ip
命令配置。
- 属于
支持多种协议
- 如以太网、Wi-Fi、PPP、虚拟网卡(tun/tap)等。
没有设备号(major/minor)
- 不属于字符或块设备,因此不参与
dev_t
编号系统。
- 不属于字符或块设备,因此不参与
第3章 设备驱动框架
3.1 驱动框架
3.1 程序调用流程
第4章 重要驱动函数
4.1 调试信息
级别名称(宏) | 数字 | 描述(用途) |
---|---|---|
KERN_EMERG |
0 |
紧急(Emergency):系统崩溃,几乎无法运行。如:"System is down" |
KERN_ALERT |
1 |
警报(Alert):必须立即处理的问题。如:"Kernel panic" |
KERN_CRIT |
2 |
严重(Critical):严重错误,如硬件故障、关键服务失败。 |
KERN_ERR |
3 |
错误(Error):运行时错误,影响功能但系统仍可运行。 |
KERN_WARNING |
4 |
警告(Warning):潜在问题,可能出错,但尚未失败。 |
KERN_NOTICE |
5 |
注意(Notice):正常但重要的情况,需引起注意。 |
KERN_INFO |
6 |
信息(Informational):普通信息,如设备初始化成功。 |
KERN_DEBUG |
7 |
调试(Debug):调试信息,仅开发时使用,生产环境通常关闭。 |
printk(KERN_INFO "This is an info message\n");
printk(KERN_ERR "Failed to allocate memory\n");
printk(KERN_DEBUG "Debug: i = %d\n", i);