对设备模型的简单理解

1.为什么要引用设备模型呢?

设备模型简单来说就是一套用数据结构搭建起来的模型,内核通过使用该模型支持了多种不同的任务,包括:

①:电源管理和系统关机

设备模型能够使操作系统以正确的顺序遍历系统硬件。

②:与用户空间通信

Sysfs文件系统向用户空间提供系统信息以及改变操作参数的结构。

③:热插拔事件

④:设备类型

系统中许多部分对设备如何连接不感兴趣,但是他们需要知道哪些类型设备是可用的,设备模型提供了将设备分类的机制。

⑤:对象的生命周期

上述的许多功能,包括热插拔支持和sysfs,使得内核中管理对象的工作变得更复杂,设备模型需要创造一套机制来管理对象的生命周期。

2.设备模型的基础

一个重要的内核数据结构——struct kobject(在这里,将kobject想象成Linux驱动模型中的根类)

当向内核成功添加一个kobject对象后,底层的代码会自动在/sys目录下生成一个子目录。另外,kobject可以附加一些属性,并绑定操作这些属性的方法,当向内核成功添加一个kobject对象后,其附加的属性会被底层的代码自动实现为对象对应目录下的文件,用户访问这些文件最终就变成了调用操作属性的方法来访问其属性。最后,通过sys的API接口可以将两个kobject对象关联起来,形成软链接。

除了struct kobject类,还有一个叫struct kset的类,它是多个kobject对象的集合,也就是多个kobject对象可以通过一个kset集合在一起。kset本身也内嵌了kobject,它可以作为集合中的kobject对象的父对象,从而在kobject之间形成父子关系,这种父子关系在/sys目录下体现为父目录和子目录的关系。而属于同一集合的kobject对象形成兄弟关系,在/sys目录下体现为同级目录。kset也可以附加属性,从而在对应的目录下产生文件。

3.总线、设备、驱动三者的关系

先来张图直观感受一下

对设备模型的简单理解

总线、设备、驱动(bus、device、driver)在内核中都有对应的结构体,在include/linux/device.h 里定义。

具体的结构体代码可以参考https://blog.****.net/fengyuwuzu0519/article/details/74503650

 

以一台拥有USB总线的计算机系统为例;

当接入一个USB设备时,USB总线会立即感知到这件事,并去遍历所有注册在USB总线上的驱动(在这个过程中可能会自动加载一个USB驱动),然后调用驱动中的一段代码来探测是否能够驱动刚插入的USB设备,如果可以,那么总线完成驱动和设备之间的绑定。即,总线是联系两者之间的桥梁,是一条重要的纽带。

要想更好的理解Linux设备模型里的这三种对象,则不得不去知道它们各自所对应的类

struct bus_type代表总线、 struct device代表设备、 struct device_driver代表驱动。这三者都内嵌有struct kobject或struct kset,于是就会生成对应的总线、设备和驱动的目录。另外Linux内核还为这些kobject对象和kset对象附加了很多属性,于是也产生了很多对应目录下的文件。可以这样认为,总线、设备和驱动都继承自同一个基类struct kobject。

 

4.如何实现驱动的自动加载

比如说,在我们插入一个USB设备后,那么其对应的驱动应该自动加载,而不是由用户去手动加载。

那么想要做到这一点,就必须要利用到一个工具——udev,在嵌入式系统中通常使用的是mdev,其功能要比udev弱许多,但也可以移植udev到嵌入式系统上。

(udev/mdev)是一个用户空间的应用程序,捕获来自内核空间发来的事件,然后根据其规则文件进行操作。udev的规则文件为

/etc/udev/rules.d目录下后缀为 .rules 的文件。

udev规则文件用#来注释,除此之外的就是一条一条的规则。每条规则至少包含一个键值对,键分为匹配和赋值两种类型。如果内核发来的事件匹配了规则中的所有匹配键的值,那么这条规则就可以得到应用,并且赋值键被赋予指定的值。

在Ubuntu中自动加载驱动的规则如下,请将这条规则添加到/etc/udev/rules.d/40-modprobe.rules 文件中,如果没有这个文件请新建一个。

ENV{MODALIAS}=="?*",   RUN+="/sbin/modprobe $env {MODALIAS}"

 

5.如何实现设备节点的自动创建(应用层)

mdev创建设备节点有两种方法,一种是运行mdev -s命令,一种是实时捕获热插拔事件。mdev -s命令通常在根文件系统挂载完成后运行一次,它将递归扫描 /sys/block 目录和 /sys/class目录下的文件, 根据文件的内容来调用 make_device自动创建设备文件。另外一种情况则是当内核发生了热插拔事件后,mdev会自动被调用,这体现在根文件系统中的 /etc/init.d/rcS初始化脚本文件中。

echo /sbin/mdev > /proc/sys/kernel/hotplug