现在的位置: 首页 > Linux驱动开发 > 正文
对linux的设备模型的理解
2012年10月19日 Linux驱动开发 ⁄ 共 4161字 暂无评论 ⁄ 被围观 1,395 views+
扫描仪打印机USB驱动程序开发外包

Linux的设备模型

顾名思义,Linux设备模型是关于设备的模型,对咱们写驱动的和不写驱动的人来说,设备的概念就是总线和与其相连的各种设备了。电脑城的IT工作者都会知道设备是通过总线连到计算机上的,而且还需要对应的驱动才能用,可是系统总线是如何发现设备的?

设备又是如何和驱动对应起来的?它们的关系如何?这些疑问的中心思想中心词汇就是总线、设备和驱动,没错,它们都是咱们这里要聊的Linux设备模型的“名角”。

总线、设备、驱动,也就是bus、device、driver,既然是“名角”。

在Linux内核中都会有它们自己专属的结构:

在include/linux/device.h中定义:
struct bus_type {
const char * name;
struct module * owner;

struct kset subsys;
struct kset drivers;
struct kset devices;
struct klist klist_devices;
struct klist klist_drivers;

struct blocking_notifier_head bus_notifier;

struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
struct bus_attribute drivers_autoprobe_attr;
struct bus_attribute drivers_probe_attr;

int (*match)(struct device * dev, struct device_driver * drv);
int (*uevent)(struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
int (*probe)(struct device * dev);
int (*remove)(struct device * dev);
void (*shutdown)(struct device * dev);

int (*suspend)(struct device * dev, pm_message_t state);
int (*suspend_late)(struct device * dev, pm_message_t state);
int (*resume_early)(struct device * dev);
int (*resume)(struct device * dev);

unsigned int drivers_autoprobe:1;
};

struct device_driver {
const char * name;
struct bus_type * bus;

struct kobject kobj;
struct klist klist_devices;
struct klist_node knode_bus;

struct module * owner;
const char * mod_name; /* used for built-in modules */
struct module_kobject * mkobj;

int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state);
int (*resume) (struct device * dev);
};

struct device {
struct klist klist_children;
struct klist_node knode_parent; /* node in sibling list */
struct klist_node knode_driver;
struct klist_node knode_bus;
struct device *parent;

struct kobject kobj;
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
struct device_type *type;
unsigned is_registered:1;
unsigned uevent_suppress:1;
struct device_attribute uevent_attr;
struct device_attribute *devt_attr;

struct semaphore sem; /* semaphore to synchronize calls to
* its driver.
*/

struct bus_type * bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
device */
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
struct dev_pm_info power;

#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */

struct list_head dma_pools; /* dma pools (if dma'ble) */

struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata archdata;

spinlock_t devres_lock;
struct list_head devres_head;

/* class_device migration path */
struct list_head node;
struct class *class;
dev_t devt; /* dev_t, creates the sysfs "dev" */
struct attribute_group **groups; /* optional groups */

void (*release)(struct device * dev);
};

有没有发现它们的共性是什么?对,它们很长,很复杂。不过不妨把它们看成艺术品,既然是艺术品,当然不会让你那么容易就看懂了。

让我们平心静气地看一下上面代码的结构,我们会发现,struct bus_type中有成员struct kset drivers 和struct kset devices,同时struct device中有两个成员struct bus_type * bus和struct device_driver *driver,struct device_driver中有两个成员struct bus_type * bus和struct klist klist_devices。先不说什么是klist、kset,光从成员的名字看,它们就是一个完美的三角关系。

我们可以知道struct device中的bus表示这个设备连到哪个总线上,driver表示这个设备的驱动是什么。struct device_driver中的bus表示这个驱动属于哪个总线,klist_devices表示这个驱动都支持哪些设备,因为这里device是复数, 又是list,更因为一个驱动可以支持多个设备,而一个设备只能绑定一个驱动。当然,struct bus_type中的drivers和devices分别表示了这个总线拥有哪些设备和哪些驱动。

我们还需要看一看什么是klist和kset。还有上面device和driver结构中出 现的kobject结构是什么?我可以肯定地告诉你,kobject和kset都是Linux设备模型中最基本的元素,总线、设备、驱动是西 瓜,kobjcet、klist是种瓜的人,没有幕后种瓜人的汗水不会有清爽解渴的西瓜。

我们不能光知道西瓜是多么的甜,还要知道种瓜人的辛苦。 kobject和kset不会在意自己的得失,它们存在的意义在于把总线、设备和驱动这样的对象连接到设备模型上。种瓜的人也不会在意自己的汗水,在意的 只是能不能种出甜蜜的西瓜。

首先要理解模型里的基石kobject以及kset的作用.网上许多介绍它们在设备模型中的地位,就不重复了。想深究的童鞋可以看看lib/kobject.c文件当中的一些函数.如kobject_add,kset_register等函数。可以帮助理解,而且在以后分析时也用得着.

设备模型主要理清了总线、设备和驱动三者之间的关系,fudan_abc分析的相当有趣.可感觉不太深入。感情去可以去其blog上找。

采用up-bottom方式.从总线开始分析,入口就在drivers/base/bus.c文件中的
int bus_register(struct bus_type *bus)函数当中.认真阅读该函数,并理解其调用函数.就可以更加深入的理解kobject以及kset在设备模型中的作用.差不多设备模型的骨架就可以摸清楚了.我从该函数中画出了一张结构图作为总结.
Linux总线、设备和驱动三者之间的关系图
从图中就可以知道.内核所知道的所有总线都在bus_kset容器当中.而从总线中又可以找到连接到该总线设备容器以及驱动容器.当然这种说法是不完全正确的.可以这样理解,这都是通过kobject以及kset来到达的一种层次式的结构。连接到某总线的设备以及驱动之间也有关系,有空再看。

对linux的设备模型的理解-下篇:linux的设备模型浅析





扫描仪打印机USB驱动程序开发外包

给我留言

您必须 [ 登录 ] 才能发表留言!

最活跃的读者

网站统计

    日志:69篇
    评论:0条
    分类:7个
    标签:150个
    链接:3个
    网站运行:3916天
最后更新:2017年8月3日
×