Linux驱动编程
Linux驱动编程
一、Linux驱动模型
Linux中的驱动模型遵循一个基本的逻辑:设备和驱动分离。其中设备是一个结构体,用于描述设备的硬件信息,例如LED的设备应当描述LED的引脚。驱动是另一个结构体,用于描述操作,例如LED的驱动应该包含LED的开或关的控制。只有当两个结构体绑定在一起时。驱动就会根据设备描述的信息操作设备。例如有两个LED灯需要控制,那么就应该有两个LED设备和一个LED驱动。当LED1绑定驱动时就会控制LED1的引脚,当LED2绑定驱动时就会控制LED2的引脚。
硬件设备和驱动的描述方式可能不同,但是在Linux的驱动模型中最终都会转化为设备结构体和驱动结构体。并通过匹配机制将设备和驱动绑定在一起。
在Linux设备模型出现后,Linux中只有一种驱动模型(设备-总线-驱动模型)。初学者可能以为设备树等和基本的总线式驱动模型不同,是不同的模型。其实不然,后面进行详细介绍。
1. 设备-总线-驱动模型
该模型是在Linux系统中有一个结构体,结构体两端分别挂设备和驱动。当有新挂载的驱动时将新的驱动与已经挂载的设备相比较,如果合适则将驱动和设备绑定。这个在设备和驱动之间的结构体就是总线。
这个总线和实际硬件中总线没有什么关系。只是将有公共操作的驱动和设备放在同一个总线上,由总线实现这一部分公共操作,就不用在每个驱动中都实现这一部分公共操作。因此在Linux系统中的i2c总线只是总线模型在i2c接口上的实现。在i2c总线中会实现i2c的基本操作,例如i2c读写。挂载在i2c总线上的驱动就不需要再实现i2c的操作。与实际硬件无关的总线:platform总线,该总线与任何硬件设备无关,完全是虚拟的。
在这个模型中设备和驱动在注册到系统之前都需要描述对应的总线。设备和驱动都是结构体,填充数据后通过注册方法挂载到总线上。
设备和驱动是否合适需要通过总线驱动提供的match函数进行比对。因此总线可以决定总线上的设备和驱动的匹配方式。
2. 设备树
设备树是一个文件,文件中描述了所有的硬件信息,包括处理器本身的信息和开发板的硬件信息。因此设备树在不同的开发板、不同的芯片上都是不同的。下面是uart的描述,关于设备树的细节参考设备树语法。设备树中包括了硬件的基本信息,包括设备寄存器的起始地址,使用的中断等。
uart0: uart@11040000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x11040000 0x1000>;
interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock SS928V100_UART0_CLK>;
clock-names = "apb_pclk";
/* dmas = <&edmacv310_0 20 20>, <&edmacv310_0 21 21>; */
/* dma-names = "rx","tx"; */
status = "disabled";
};
uart1: uart@11041000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x11041000 0x1000>;
interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clock SS928V100_UART1_CLK>;
clock-names = "apb_pclk";
/* dmas = <&edmacv310_0 22 22>, <&edmacv310_0 23 23>; */
/* dma-names = "rx","tx"; */
status = "disabled";
};
设备树并不是区别与总线模型的另一个模型,而是总线模型的补充。在原来的总线模型中只能通过C源文件中的设备结构体描述设备。这种方式导致每次修改设备信息都需要重新编译。设备树出现后通过设备树描述硬件设备,在系统启动时分析设备树并创建设备结构体。此时结构体中并没有设备的全部信息,但是of_node属性已经被填充,of_node代表当前设备对应的设备树节点。随后系统根据设备树节点的compatible属性与驱动的of_match_table中的compatible属性相匹配,匹配成功则将两者绑定并调用驱动的probe函数,将匹配到的设备传递给probe函数。probe函数通过of_node节点分析当前设备的其他属性并填充设备结构体,以保证后续的操作。
3. id_table
id_table模型通过id_table表进行驱动和设备的匹配,一般通过匹配id_table中的name属性确定是否匹配,id_table允许一个data属性,当前驱动可以同时驱动不同类型的设备时data属性可以用来描述不同设备间的不同。
任何设备和驱动都有其所在的总线,当设备或驱动挂载成功后调用对应总线的match函数进行匹配,而设备树匹配和id_table匹配则是在match函数中实现的。因此具体的匹配顺序需要根据总线的match函数进行分析。
二、具体驱动结构简介
Linux驱动模型的核心结构是device结构体和device_driver结构体。device代表着系统中的设备,device_driver代表着系统中的驱动。其它设备或驱动都是由这两个结构体继承(C语言的方式实现面向对象)而来。
以I2C驱动为例:
struct i2c_driver {
/* ... */
struct device_driver driver;//i2c驱动的结构体中包含driver结构体
/* ... */
};
I2C设备的匹配:
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
/* 通过设备树的compatible 属性匹配*/
if (i2c_of_match_device(drv->of_match_table, client))
return 1;
/* ACPI 方式匹配 */
if (acpi_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* id_table匹配 */
if (i2c_match_id(driver->id_table, client))
return 1;
return 0;
}
如果以上三种方式都不能匹配到,则匹配失败。首先使用的设备树进行匹配,因此在i2c的设备驱动中,设备树中出现节点的compatible与驱动的compatible属性对应即可匹配成功。也可以使用id_table进行匹配。
附录一:Linux驱动的发展历程
(来自网络查询,未经证实)
在2.5版本内引入include/linux/device.h,其中包括device、device_driver结构体。
在2.6.0版本引入bus_type结构体,同时引入cdev
在2.6.14版本引入设备树
字符设备文件、块设备文件是Linux中描述设备的文件
以下文字是对ChatGPT问答的总结
Linux中最早期使用/dev文件夹管理设备,对应的文件系统是devfs。devfs对每一个设备提供一个设备文件,应用层可以通过读写等方式控制外部设备。后续发展的过程中,Linux开始构建驱动模型,并通过/sys(sysfs文件系统)下的文件描述设备。/sys和/dev的区别是,一个设备在/dev下表现为一个设备文件,在/sys表现为一个目录,目录中包括设备的属性状态等被列为单独的文件。
下面是块设备文件sda在/dev中对应的设备文件
brw-rw---- 1 root disk 8, 0 5月 5 08:59 sda
下面是块设备文件sda在/sys中对应的文件夹
-r--r--r-- 1 root root 4096 5月 5 13:41 alignment_offset
lrwxrwxrwx 1 root root 0 5月 5 13:41 bdi -> ../../../../../../../../../virtual/bdi/8:0
-r--r--r-- 1 root root 4096 5月 5 13:41 capability
-r--r--r-- 1 root root 4096 5月 5 08:59 dev
lrwxrwxrwx 1 root root 0 5月 5 09:01 device -> ../../../2:0:0:0
-r--r--r-- 1 root root 4096 5月 5 13:41 discard_alignment
-r--r--r-- 1 root root 4096 5月 5 13:41 events
-r--r--r-- 1 root root 4096 5月 5 13:41 events_async
-rw-r--r-- 1 root root 4096 5月 5 13:41 events_poll_msecs
-r--r--r-- 1 root root 4096 5月 5 13:41 ext_range
-r--r--r-- 1 root root 4096 5月 5 13:41 hidden
drwxr-xr-x 2 root root 0 5月 5 13:41 holders
-r--r--r-- 1 root root 4096 5月 5 13:41 inflight
drwxr-xr-x 2 root root 0 5月 5 13:41 integrity
drwxr-xr-x 3 root root 0 5月 5 13:41 mq
drwxr-xr-x 2 root root 0 5月 5 13:41 power
drwxr-xr-x 3 root root 0 5月 5 08:59 queue
-r--r--r-- 1 root root 4096 5月 5 13:41 range
-r--r--r-- 1 root root 4096 5月 5 08:59 removable
-r--r--r-- 1 root root 4096 5月 5 08:59 ro
-r--r--r-- 1 root root 4096 5月 5 08:59 size
drwxr-xr-x 2 root root 0 5月 5 13:41 slaves
-r--r--r-- 1 root root 4096 5月 5 13:41 stat
lrwxrwxrwx 1 root root 0 5月 5 08:59 subsystem -> ../../../../../../../../../../class/block
drwxr-xr-x 2 root root 0 5月 5 13:41 trace
-rw-r--r-- 1 root root 4096 5月 5 08:59 uevent
参考文献
- 分享
- 举报
-
浏览量:1481次2020-08-07 17:15:53
-
浏览量:1233次2022-10-10 11:44:39
-
浏览量:659次2023-08-14 17:53:58
-
浏览量:1740次2023-05-16 15:43:05
-
浏览量:932次2023-05-06 13:40:15
-
浏览量:1461次2023-12-28 14:40:29
-
浏览量:2331次2020-08-18 20:05:11
-
浏览量:4019次2020-12-28 10:36:15
-
浏览量:1509次2024-03-16 10:01:36
-
浏览量:630次2023-08-22 13:38:20
-
浏览量:2592次2023-11-10 15:46:07
-
浏览量:2764次2017-11-20 16:03:39
-
浏览量:871次2023-06-12 14:34:15
-
浏览量:1391次2024-01-12 15:17:33
-
浏览量:6700次2022-02-19 16:25:21
-
浏览量:5206次2017-11-18 16:34:44
-
浏览量:2098次2020-04-22 18:00:18
-
浏览量:1590次2018-03-15 13:10:40
-
浏览量:2313次2020-07-28 11:05:08
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
cxcc
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明