> Linux教程 > linux基础 >

linux文件系统的系统分析--(十三)sysfs和设备模型--Device

      分析完了bus,接下来分析device:

      同样在driver_init-->devices_init

 

[cpp] view plain copy
 
  1. <span style="font-family:'Liberation Serif', serif;">int __init devices_init(void)  
  2. {  
  3.     devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);  
  4.     if (!devices_kset)  
  5.         return -ENOMEM;  
  6.     dev_kobj = kobject_create_and_add("dev", NULL);  
  7.     if (!dev_kobj)  
  8.         goto dev_kobj_err;  
  9.     sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);  
  10.     if (!sysfs_dev_block_kobj)  
  11.         goto block_kobj_err;  
  12.     sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);  
  13.     if (!sysfs_dev_char_kobj)  
  14.         goto char_kobj_err;  
  15.   
  16.     return 0;  
  17.   
  18.  char_kobj_err:  
  19.     kobject_put(sysfs_dev_block_kobj);  
  20.  block_kobj_err:  
  21.     kobject_put(dev_kobj);  
  22.  dev_kobj_err:  
  23.     kset_unregister(devices_kset);  
  24.     return -ENOMEM;  
  25. }</span>  

       /sys目录下有了devices目录和dev目录,dev下面有blockchar两个目录

 

 

       设备的注册:

 

[cpp] view plain copy
 
  1. <span style="font-family:'Liberation Serif', serif;">int device_register(struct device *dev)  
  2. {  
  3.     device_initialize(dev);  
  4.     return device_add(dev);  
  5. }  
  6. </span>  


 

  1. 设备的初始化device_initialize

void device_initialize(structdevice *dev)

{

dev->kobj.kset =devices_kset; //这个device结构体内嵌的kobject代表的目录在/sys/devices

kobject_init(&dev->kobj,&device_ktype); //初始化内嵌的kobjectkobj_typedevice_ktype

INIT_LIST_HEAD(&dev->dma_pools);

init_MUTEX(&dev->sem);

spin_lock_init(&dev->devres_lock);

INIT_LIST_HEAD(&dev->devres_head);

device_init_wakeup(dev, 0);

device_pm_init(dev);

set_dev_node(dev, -1);

}

  1. 添加设备device_add

2.1、初始化devicestructdevice_private *p;指针

int device_private_init(structdevice *dev)

{

dev->p =kzalloc(sizeof(*dev->p), GFP_KERNEL);

if (!dev->p)

return -ENOMEM;

dev->p->device = dev; //指向dev

klist_init(&dev->p->klist_children,klist_children_get,

klist_children_put); //初始化klist_children链表

return 0;

}

2.2、设置device结构体内嵌的kobject的名称

2.3setup_parent(dev,parent);

根据device结构体的父子层次关系设置内嵌kobject对象的父子层次关系

2.4、在kobject层注册device内嵌的kobject对象

2.5、创建设备属性文件ueventuevent文件的读写与kobject_uevent相关

2.6、如果device结构体的devt设备号存在,那么创建devt属性文件文件,从这个属性文件中可以读出设备号;sysfs中会创建链接文件;devtmpfs会创建结点node

2.7、设备添加class的链接文件

2.8、添加设备属性文件

2.9bus_add_device(dev); 添加设备到总线

A、添加设备的总线属性:bus->dev_attrs

B、创建链接文件

C、添加设备到总线的设备链表中:

klist_add_tail(&dev->p->knode_bus,&bus->p->klist_devices);

2.10bus_probe_device(dev);device探测driver

bus_probe_device-->device_attach

如果dev的driver指针已经指向了driver结构体,那么调用device_bind_driver将device和driver绑定,否则调用

bus_for_each_drv(dev->bus, NULL, dev, __device_attach);对于bus总线klist_drivers链表上所有挂着的driver,都

来和我们的device进行匹配,负责的函数就是__device_attach

 

如果devdriver指针已经

static int__device_attach(struct device_driver *drv, void *data)

{

struct device *dev = data;

 

if (!driver_match_device(drv,dev))

return 0;

 

return driver_probe_device(drv,dev);

}

首先调用总线级别的match函数,然后调用driver_probe_device(drv,dev);

driver_probe_device-->really_probe-->dev->bus->probe(dev);以及drv->probe(dev);

最后调用driver_bound

klist_add_tail(&dev->p->knode_driver,&dev->driver->p->klist_devices);

 

                       devices的注册过程就如上所述,至于最后的bus_probe_device具体是怎么实现的?等到分析完busdevice driverclass后,再举一个实例来具体分析。

(责任编辑:IT)