linux文件系统的系统分析--(十三)sysfs和设备模型--Device
时间:2016-02-22 13:08 来源:linux.it.net.cn 作者:IT
分析完了bus,接下来分析device:
同样在driver_init-->devices_init
-
<span style="font-family:'Liberation Serif', serif;">int __init devices_init(void)
-
{
-
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
-
if (!devices_kset)
-
return -ENOMEM;
-
dev_kobj = kobject_create_and_add("dev", NULL);
-
if (!dev_kobj)
-
goto dev_kobj_err;
-
sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
-
if (!sysfs_dev_block_kobj)
-
goto block_kobj_err;
-
sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
-
if (!sysfs_dev_char_kobj)
-
goto char_kobj_err;
-
-
return 0;
-
-
char_kobj_err:
-
kobject_put(sysfs_dev_block_kobj);
-
block_kobj_err:
-
kobject_put(dev_kobj);
-
dev_kobj_err:
-
kset_unregister(devices_kset);
-
return -ENOMEM;
-
}</span>
/sys目录下有了devices目录和dev目录,dev下面有block和char两个目录
设备的注册:
-
<span style="font-family:'Liberation Serif', serif;">int device_register(struct device *dev)
-
{
-
device_initialize(dev);
-
return device_add(dev);
-
}
-
</span>
-
设备的初始化device_initialize
void device_initialize(structdevice *dev)
{
dev->kobj.kset =devices_kset; //这个device结构体内嵌的kobject代表的目录在/sys/devices下
kobject_init(&dev->kobj,&device_ktype); //初始化内嵌的kobject,kobj_type为device_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);
}
-
添加设备device_add
2.1、初始化device的structdevice_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.3、setup_parent(dev,parent);
根据device结构体的父子层次关系设置内嵌kobject对象的父子层次关系
2.4、在kobject层注册device内嵌的kobject对象
2.5、创建设备属性文件uevent,uevent文件的读写与kobject_uevent相关
2.6、如果device结构体的devt设备号存在,那么创建devt属性文件文件,从这个属性文件中可以读出设备号;sysfs中会创建链接文件;devtmpfs会创建结点node;
2.7、设备添加class的链接文件
2.8、添加设备属性文件
2.9、bus_add_device(dev); 添加设备到总线
A、添加设备的总线属性:bus->dev_attrs
B、创建链接文件
C、添加设备到总线的设备链表中:
klist_add_tail(&dev->p->knode_bus,&bus->p->klist_devices);
2.10、bus_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
如果dev的driver指针已经
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 driver和class后,再举一个实例来具体分析。
(责任编辑:IT)
分析完了bus,接下来分析device: 同样在driver_init-->devices_init
/sys目录下有了devices目录和dev目录,dev下面有block和char两个目录
设备的注册:
void device_initialize(structdevice *dev) { dev->kobj.kset =devices_kset; //这个device结构体内嵌的kobject代表的目录在/sys/devices下 kobject_init(&dev->kobj,&device_ktype); //初始化内嵌的kobject,kobj_type为device_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); }
2.1、初始化device的structdevice_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.3、setup_parent(dev,parent); 根据device结构体的父子层次关系设置内嵌kobject对象的父子层次关系 2.4、在kobject层注册device内嵌的kobject对象 2.5、创建设备属性文件uevent,uevent文件的读写与kobject_uevent相关 2.6、如果device结构体的devt设备号存在,那么创建devt属性文件文件,从这个属性文件中可以读出设备号;sysfs中会创建链接文件;devtmpfs会创建结点node; 2.7、设备添加class的链接文件 2.8、添加设备属性文件 2.9、bus_add_device(dev); 添加设备到总线 A、添加设备的总线属性:bus->dev_attrs B、创建链接文件 C、添加设备到总线的设备链表中: klist_add_tail(&dev->p->knode_bus,&bus->p->klist_devices); 2.10、bus_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
如果dev的driver指针已经 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 driver和class后,再举一个实例来具体分析。 (责任编辑:IT) |