分析完了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) |