gdt-A20

导航

linux设备模型之bus,device,driver分析一

===============================
本文系本站原创,欢迎转载!
转载请注明出处:http://www.cnblogs.com/gdt-a20

===============================

    内核的开发者将总线,设备,驱动这三者用软件思想抽象了出来,巧妙的建立了其间的关系,使之更形象化。结合前面所学的知识,总的来说其三者间的关系为bus有两条链表,分别用于挂接设备和驱动,指定了其自身bus的device或者driver最后都会分别连接到对应bus的这两条链表上,而总线又有其始端,为bus_kset,一个driver可以对应于几个设备,因此driver同样有其设备链表,用于挂接可以操作的设备,其自身也有bus挂接点,用于将自身挂接到对应bus(每个driver只属于一条总线),而对于device,一个设备只属于一条总线,只能有一个driver与其对应,因此对于device,都是单一的,一个driver挂接点,一个bus挂接点,device与bus相同的是都有始端,device为devices_kset,因此device的注册同时会出现在对应的bus目录和device总目录下。好了,下面就以源码为例分别分析一下bus,device,driver的注册过程。

 

一、bus的注册

      bus的注册比较简单,首先来看一下bus的结构:

     

 1 struct bus_type {
2 const char *name; //名字
3 struct bus_attribute *bus_attrs; //bus属性集
4 struct device_attribute *dev_attrs; //device属性集
5 struct driver_attribute *drv_attrs; //driver属性集
6 int (*match)(struct device *dev, struct device_driver *drv);
7 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
8 int (*probe)(struct device *dev);
9 int (*remove)(struct device *dev);
10 void (*shutdown)(struct device *dev);
11 int (*suspend)(struct device *dev, pm_message_t state);
12 int (*resume)(struct device *dev);
13 const struct dev_pm_ops *pm;
14 struct bus_type_private *p; //bus的私有成员
15 };
16 //其中重点看一下私有成员结构体:
17 struct bus_type_private {
18 struct kset subsys; //bus内嵌的kset,代表其自身
19 struct kset *drivers_kset;
20 struct kset *devices_kset;
21 struct klist klist_devices; //包含devices链表及其操作函数
22 struct klist klist_drivers; //driver链表及其操作函数
23 struct blocking_notifier_head bus_notifier;
24 unsigned int drivers_autoprobe:1; //匹配成功自动初始化标志
25 struct bus_type *bus;
26 };

 

  无论是bus,driver,还是device其本身特征都放在私有成员里,其注册时,都会申请并填充这个结构体,下面具体分析一下bus的注册流程,从bus_register开始:

     

 1 int bus_register(struct bus_type *bus)
2 {
3 int retval;
4 struct bus_type_private *priv;
5 priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL); //进入时bus_type->bus_type_private为NULL
6 if (!priv) //该函数主要是对其的设置
7 return -ENOMEM;
8 priv->bus = bus; //私有成员的bus回指该bus
9 bus->p = priv; //初始化bus->p,即其私有属性
10 BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
11 retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); //设置该bus的名字,bus是kset的封装
12 if (retval)
13 goto out;
14 //bus_kset即为所有bus的总起始端点
15 //围绕bus内嵌的kset初始化,和kset的初始化时围绕
16 priv->subsys.kobj.kset = bus_kset; //kobj相似,没有parent时,就会用kset的kobj,此处即是
17 priv->subsys.kobj.ktype = &bus_ktype; //属性操作级别统一为bus_ktype
18 priv->drivers_autoprobe = 1; //设置该标志,当有driver注册时,会自动匹配devices
19 //上的设备并用probe初始化,
20 //当有device注册时也同样找到 driver并会初始化
21 retval = kset_register(&priv->subsys); //注册kset,创建目录结构,以及层次关系
22 if (retval)
23 goto out;
24 retval = bus_create_file(bus, &bus_attr_uevent); //当前bus目录下生成bus_attr_uevent属性文件
25 if (retval)
26 goto bus_uevent_fail;
27 priv->devices_kset = kset_create_and_add("devices", NULL, //初始化bus目录下的devices目录,里面级联了该bus下设备,
28 &priv->subsys.kobj); //仍然以kset为原型
29 if (!priv->devices_kset) {
30 retval = -ENOMEM;
31 goto bus_devices_fail;
32 }
33 priv->drivers_kset = kset_create_and_add("drivers", NULL, //初始化bus目录下的drivers目录,里面级联了该bus下设备的driver
34 &priv->subsys.kobj);
35 if (!priv->drivers_kset) {
36 retval = -ENOMEM;
37 goto bus_drivers_fail;
38 }
39 klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); //初始化klist_devices里的操作函数成员
40 klist_init(&priv->klist_drivers, NULL, NULL); //klist_drivers里的操作函数置空
41 retval = add_probe_files(bus); //增加bus_attr_drivers_probe和bus_attr_drivers_autoprobe
42 if (retval) //属性文件
43 goto bus_probe_files_fail;
44 retval = bus_add_attrs(bus); //增加默认的属性文件
45 if (retval)
46 goto bus_attrs_fail;
47 pr_debug("bus: '%s': registered/n", bus->name);
48 return 0;
49 bus_attrs_fail: //以下为错误处理
50 remove_probe_files(bus);
51 bus_probe_files_fail:
52 kset_unregister(bus->p->drivers_kset);
53 bus_drivers_fail:
54 kset_unregister(bus->p->devices_kset);
55 bus_devices_fail:
56 bus_remove_file(bus, &bus_attr_uevent);
57 bus_uevent_fail:
58 kset_unregister(&bus->p->subsys);
59 out:
60 kfree(bus->p);
61 bus->p = NULL;
62 return retval;
63 }

 

   由此可见,bus又是kset的封装,bus_register主要完成了其私有成员bus_type_private的初始化,并初始化了其下的两个目录devices和drivers,及其属性文件,bus有个自己的根目录也就是bus有个起始端点,是bus_kset,经过此番的注册,bus目录下将会出现我们注册的bus,并且其下会有device和driver两个子目录,代表它下面的driver和device链表。

二、driver的注册

  下面看一下driver是怎么和bus关联起来的,首先看下driver的结构:

    

 1 struct device_driver {
2 const char *name; //名字
3 struct bus_type *bus; //其所在的bus
4 struct module *owner;
5 const char *mod_name; /* used for built-in modules */
6 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
7 #if defined(CONFIG_OF)
8 const struct of_device_id *of_match_table;
9 #endif
10 int (*probe) (struct device *dev); //匹配成功时可能会调用到的函数
11 int (*remove) (struct device *dev);
12 void (*shutdown) (struct device *dev);
13 int (*suspend) (struct device *dev, pm_message_t state);
14 int (*resume) (struct device *dev);
15 const struct attribute_group **groups;
16 const struct dev_pm_ops *pm;
17 struct driver_private *p; //私有成员,表示driver
18 };
19 //重点看下driver的私有成员
20 struct driver_private {
21 struct kobject kobj; //代表driver自身
22 struct klist klist_devices; //可以操控的设备链表
23 struct klist_node knode_bus; //挂接到bus的节点
24 struct module_kobject *mkobj; //模块相关
25 struct device_driver *driver; //回指该driver
26 };

 

  如同bus一样,重点的仍是可以代表其自身的私有属性,下面具体看一下driver的注册过程,从driver_register开始:

    

  1 int driver_register(struct device_driver *drv)
2 {
3 int ret;
4 struct device_driver *other;
5 BUG_ON(!drv->bus->p);
6 if ((drv->bus->probe && drv->probe) || //driver和bus的同名操作函数如果同时存在,会出现警告
7 (drv->bus->remove && drv->remove) || //并且会优先选用bus的
8 (drv->bus->shutdown && drv->shutdown))
9 printk(KERN_WARNING "Driver '%s' needs updating - please use "
10 "bus_type methods/n", drv->name);
11 other = driver_find(drv->name, drv->bus); //进入bus的driver链表,确认该driver是否已经注册
12 if (other) {
13 put_driver(other); //找到了再减少引用计数,并且报错退出
14 printk(KERN_ERR "Error: Driver '%s' is already registered, "
15 "aborting.../n", drv->name);
16 return -EBUSY;
17 }
18 ret = bus_add_driver(drv); //如果没有注册,那么把该driver加入所在bus
19 if (ret)
20 return ret;
21 ret = driver_add_groups(drv, drv->groups);
22 if (ret)
23 bus_remove_driver(drv);
24 return ret;
25 }
26 /****************************************************
27 × 跟踪一下driver_find(drv->name, drv->bus)
28 ****************************************************/
29 struct device_driver *driver_find(const char *name, struct bus_type *bus)
30 {
31 struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); //bus->p->drivers_kset代表bus下
32 struct driver_private *priv; //的driver目录,此处会遍历bus的
33 //driver链表,通过driver内嵌的
34 if (k) { //kobj名字比较
35 priv = to_driver(k);
36 return priv->driver; //如果找到同名的kobj那么返回该driver
37 }
38 return NULL;
39 }
40 //看一下kset_find_obj吧:
41 struct kobject *kset_find_obj(struct kset *kset, const char *name)
42 {
43 struct kobject *k;
44 struct kobject *ret = NULL;
45 spin_lock(&kset->list_lock);
46 list_for_each_entry(k, &kset->list, entry) { //遍历bus下的driver链表,如果
47 if (kobject_name(k) && !strcmp(kobject_name(k), name)) { //找到那么返回找到的kobj,并且把
48 ret = kobject_get(k); //该driver的kobj引用计数+1
49 break;
50 }
51 }
52 spin_unlock(&kset->list_lock);
53 return ret;
54 }
55 /************************************************
56 × 再来跟踪一下driver_register里面的另外一个函数
57 × bus_add_driver(drv)
58 ************************************************/
59 int bus_add_driver(struct device_driver *drv)
60 {
61 struct bus_type *bus;
62 struct driver_private *priv;
63 int error = 0;
64 bus = bus_get(drv->bus); //取得其所在bus的指针
65 if (!bus)
66 return -EINVAL;
67 pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name); //开始初始化这个driver的私有成员,
68 //和bus类似
69 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
70 if (!priv) {
71 error = -ENOMEM;
72 goto out_put_bus;
73 }
74 klist_init(&priv->klist_devices, NULL, NULL); //设备操作函数清空,设备链表初始化
75 priv->driver = drv;
76 drv->p = priv;
77 priv->kobj.kset = bus->p->drivers_kset; //kset指定到bus下面
78 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, //建立层次结构和属性文件
79 "%s", drv->name);
80 if (error)
81 goto out_unregister;
82 if (drv->bus->p->drivers_autoprobe) { //bus的自动匹配如果设置为真,
83 error = driver_attach(drv); //那么到bus的devices上去匹配设备
84 if (error)
85 goto out_unregister;
86 }
87 klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //把driver挂接到bus的driver链表
88 module_add_driver(drv->owner, drv);
89 error = driver_create_file(drv, &driver_attr_uevent); //以下添加该driver相关属性文件
90 if (error) {
91 printk(KERN_ERR "%s: uevent attr (%s) failed/n",
92 __func__, drv->name);
93 }
94 error = driver_add_attrs(bus, drv);
95 if (error) {
96 /* How the hell do we get out of this pickle? Give up */
97 printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n",
98 __func__, drv->name);
99 }
100 if (!drv->suppress_bind_attrs) {
101 error = add_bind_files(drv);
102 if (error) {
103 /* Ditto */
104 printk(KERN_ERR "%s: add_bind_files(%s) failed/n",
105 __func__, drv->name);
106 }
107 }
108 kobject_uevent(&priv->kobj, KOBJ_ADD);
109 return 0;
110 out_unregister:
111 kobject_put(&priv->kobj);
112 kfree(drv->p);
113 drv->p = NULL;
114 out_put_bus:
115 bus_put(bus);
116 return error;
117 }
118 /****************************************************************
119 × 接下来就剩下最终要的匹配函数driver_attach(drv)了,我们来看一下:
120 ****************************************************************/
121 int driver_attach(struct device_driver *drv) //遍历bus的设备链表找到
122 { //合适的设备就调用__driver_attach,
123 return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); //NULL表示从头开始遍历
124 }
125 //============
126 int bus_for_each_dev(struct bus_type *bus, struct device *start,
127 void *data, int (*fn)(struct device *, void *))
128 {
129 struct klist_iter i;
130 struct device *dev;
131 int error = 0;
132 if (!bus)
133 return -EINVAL;
134 klist_iter_init_node(&bus->p->klist_devices, &i, //进入bus的devices链表
135 (start ? &start->p->knode_bus : NULL));
136 while ((dev = next_device(&i)) && !error) //设备存在则调用fn即__driver_attach
137 error = fn(dev, data); //进行匹配
138 klist_iter_exit(&i);
139 return error;
140 }
141 /*********************************************
142 × 接着看一下__driver_attach这个函数
143 *********************************************/
144 static int __driver_attach(struct device *dev, void *data)
145 {
146 struct device_driver *drv = data;
147 if (!driver_match_device(drv, dev)) //进行匹配
148 return 0;
149 if (dev->parent) /* Needed for USB */
150 device_lock(dev->parent);
151 device_lock(dev);
152 if (!dev->driver) //如果设备没有指定driver
153 driver_probe_device(drv, dev); //那么需要初始化匹配到的这个设备
154 device_unlock(dev);
155 if (dev->parent)
156 device_unlock(dev->parent);
157 return 0;
158 }
159 /*********************************************
160 × 又遇到两个分支,囧,先看一下driver_match_device
161 *********************************************/
162 static inline int driver_match_device(struct device_driver *drv, //bus的match存在就用bus的
163 struct device *dev) //,否则就直接匹配成功...
164 { //match通常实现为首先扫描
165 return drv->bus->match ? drv->bus->match(dev, drv) : 1; //driver支持的id设备表,如果
166 } //为NULL就用名字进行匹配
167 /************************************
168 × 再来看一下driver_probe_device这个函数
169 ************************************/
170 int driver_probe_device(struct device_driver *drv, struct device *dev)
171 {
172 int ret = 0;
173 if (!device_is_registered(dev)) //判断该设备是否已经注册
174 return -ENODEV;
175 pr_debug("bus: '%s': %s: matched device %s with driver %s/n",
176 drv->bus->name, __func__, dev_name(dev), drv->name);
177 pm_runtime_get_noresume(dev);
178 pm_runtime_barrier(dev);
179 ret = really_probe(dev, drv); //调用really_probe
180 pm_runtime_put_sync(dev);
181 return ret;
182 }
183 /************************************
184 × 看一下device_is_registered
185 ************************************/
186 static inline int device_is_registered(struct device *dev)
187 {
188 return dev->kobj.state_in_sysfs; //在sysfs中表示已经注册
189 }
190 /************************************
191 × 再看really_probe
192 ************************************/
193 static int really_probe(struct device *dev, struct device_driver *drv)
194 {
195 int ret = 0;
196 atomic_inc(&probe_count);
197 pr_debug("bus: '%s': %s: probing driver %s with device %s/n",
198 drv->bus->name, __func__, drv->name, dev_name(dev));
199 WARN_ON(!list_empty(&dev->devres_head));
200 dev->driver = drv; //device的driver初始化成该driver
201 if (driver_sysfs_add(dev)) {
202 printk(KERN_ERR "%s: driver_sysfs_add(%s) failed/n",
203 __func__, dev_name(dev));
204 goto probe_failed;
205 }
206 //利用probe初始化设备
207 if (dev->bus->probe) { //如果bus的probe存在就用bus的,
208 ret = dev->bus->probe(dev); //如果bus的不存在driver的存在
209 if (ret) //再用driver的
210 goto probe_failed;
211 } else if (drv->probe) {
212 ret = drv->probe(dev);
213 if (ret)
214 goto probe_failed;
215 }
216 driver_bound(dev); //调用driver_bound进行绑定
217 ret = 1;
218 pr_debug("bus: '%s': %s: bound device %s to driver %s/n",
219 drv->bus->name, __func__, dev_name(dev), drv->name);
220 goto done;
221 probe_failed:
222 devres_release_all(dev);
223 driver_sysfs_remove(dev);
224 dev->driver = NULL;
225 if (ret != -ENODEV && ret != -ENXIO) {
226 /* driver matched but the probe failed */
227 printk(KERN_WARNING
228 "%s: probe of %s failed with error %d/n",
229 drv->name, dev_name(dev), ret);
230 }
231 /*
232 * Ignore errors returned by ->probe so that the next driver can try
233 * its luck.
234 */
235 ret = 0;
236 done:
237 atomic_dec(&probe_count);
238 wake_up(&probe_waitqueue);
239 return ret;
240 }
241 /**********************************
242 * 最后跟一下driver_bound(dev)这个函数
243 **********************************/
244 static void driver_bound(struct device *dev)
245 {
246 if (klist_node_attached(&dev->p->knode_driver)) { //判断是否已经绑定
247 printk(KERN_WARNING "%s: device %s already bound/n",
248 __func__, kobject_name(&dev->kobj));
249 return;
250 }
251 pr_debug("driver: '%s': %s: bound to device '%s'/n", dev_name(dev),
252 __func__, dev->driver->name);
253 klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); //将设备添加
254 //到driver的链表
255 if (dev->bus)
256 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
257 BUS_NOTIFY_BOUND_DRIVER, dev);
258 }
259 //all end

 

  总结一下,driver的注册,主要涉及将自身挂接到bus的driver链表,并将匹配到的设备加入自己的device链表,并且将匹配到的device的driver成员初始化为该driver,私有属性的driver节点也挂到driver的设备链表下,其中匹配函数是利用利用bus的match函数,该函数通常判断如果driver有id表,就查表匹配,如果没有就用driver和device名字匹配。当匹配成功后如果自动初始化标志允许则调用初始化函数probe,bus的probe优先级始终高于driver的。另外注意一点driver是没有总的起始端点的,driver不是可具体描述的事物。

   由于篇幅比较长,device的分析放到下一篇《linux设备模型之bus,device,driver分析<二>》   ^_^!

posted on 2011-05-17 02:15  gdt-A20  阅读(2835)  评论(0编辑  收藏  举报