my代碼跟蹤之driver_register

內核代碼爲Linux Kernel:3.4.x  必備知識ldd3第十四章linux設備模型

driver_register跟蹤:紅色爲主線 藍色爲標註

/**

 *struct device_driver - The basic device driver structure

 *@name:     Name of the device driver.

 *@bus: The bus which the device of thisdriver belongs to.

 *@owner:    The module owner.

 *@mod_name:    Used for built-in modules.

 *@suppress_bind_attrs: Disables bind/unbind via sysfs.

 *@of_match_table: The open firmware table.

 *@probe:    Called to query the existenceof a specific device,

 *           whether this driver can work with it,and bind the driver

 *           to a specific device.

 *@remove:  Called when the device isremoved from the system to

 *           unbind a device from this driver.

 *@shutdown:      Called at shut-down timeto quiesce the device.

 *@suspend: Called to put the device to sleepmode. Usually to a

 *           low power state.

 *@resume:  Called to bring a device fromsleep mode.

 *@groups:   Default attributes that getcreated by the driver core

 *           automatically.

 *@pm:        Power management operations ofthe device which matched

 *           this driver.

 *@p:           Driver core's private data,no one other than the driver

 *           core can touch this.

 *

 *The device driver-model tracks all of the drivers known to the system.

 *The main reason for this tracking is to enable the driver core to match

 * updrivers with new devices. Once drivers are known objects within the

 *system, however, a number of other things become possible. Device drivers

 *can export information and configuration variables that are independent

 * ofany specific device.

 */

struct device_driver {

       constchar              *name;

       structbus_type              *bus;

 

       structmodule         *owner;

       constchar              *mod_name;   /* used for built-in modules */

 

       boolsuppress_bind_attrs;      /* disablesbind/unbind via sysfs */

 

       conststruct of_device_id       *of_match_table;

 

       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);

       conststruct attribute_group **groups;

 

       conststruct dev_pm_ops *pm;

 

       structdriver_private *p;

};

 

/**

 *driver_register - register driver with bus

 *@drv: driver to register

 *

 * Wepass off most of the work to the bus_add_driver() call,

 *since most of the things we have to do deal with the bus

 *structures.

 */

int driver_register(struct device_driver*drv)

{

       intret;

       structdevice_driver *other;

 

       BUG_ON(!drv->bus->p);      //p不存在斷言並輸出信息;其實這個主要是判斷bus是否存在 詳見標註一

 

       if((drv->bus->probe && drv->probe) ||

           (drv->bus->remove &&drv->remove) ||

           (drv->bus->shutdown &&drv->shutdown)) //driverdriver所屬busproberemoveshutdown一組存在則提示更新;主要是判斷驅動跟驅動的總線是否有衝突的函數註冊,給出警告信息

              printk(KERN_WARNING"Driver '%s' needs updating - please use "

                     "bus_typemethods\n", drv->name);

 

       other= driver_find(drv->name, drv->bus);  //bus上以namedriver;存在說明已經註冊 退出返回EBUSY詳見標註二

       if(other) {

              printk(KERN_ERR"Error: Driver '%s' is already registered, "

                     "aborting...\n",drv->name);

              return-EBUSY;

       }

 

       ret= bus_add_driver(drv);    //bus添加driver 成功返回0

       if(ret)

              returnret;

       ret= driver_add_groups(drv, drv->groups); //如果grop不爲空的話,將在驅動文件夾下創建以group名字的子文件夾,然後在子文件夾下添加group的屬性文件

       if(ret)

              bus_remove_driver(drv);       //出錯從bus上刪除driver

       returnret;

}

標註一:

BUG_ON原型爲

#define BUG_ON(condition) do { if(unlikely(condition)) BUG(); } while(0)

#define BUG()do { \

       printk("kernelBUG at %s:%d!\n", __FILE__, __LINE__); \

       panic("BUG!");\

} while (0)

標註一end

標註二:

struct device_driver *driver_find(constchar *name, struct bus_type *bus)

{

       structkobject *k = kset_find_obj(bus->p->drivers_kset, name); //bus的驅動集合裏尋找同名的驅動

       structdriver_private *priv;

 

       if(k) {

              /*Drop reference added by kset_find_obj() */

              kobject_put(k);      //如果找到減小引用計數

              priv= to_driver(k);              //通過kobject轉換成driver_private,返回相應的驅動

              returnpriv->driver;

       }

       returnNULL;

}

標註二end

int bus_add_driver(structdevice_driver *drv)

{

       structbus_type *bus;

       structdriver_private *priv;

       interror = 0;

 

       bus= bus_get(drv->bus);      //找到該drv所屬的bus,其實就是增加該bus->p->subsys->kobject->kref的引用計數

       if(!bus)

              return-EINVAL;

 

       pr_debug("bus:'%s': add driver %s\n", bus->name, drv->name);

 

       priv= kzalloc(sizeof(*priv), GFP_KERNEL);     //分配driver_private結構

       if(!priv) {

              error= -ENOMEM;

              gotoout_put_bus;

       }

       klist_init(&priv->klist_devices,NULL, NULL);  //初始化priv->klist_devices

       priv->driver= drv; //將該drv賦值給priv->driver

       drv->p= priv; //drvdrv->p又等於priv

       priv->kobj.kset= bus->p->drivers_kset;      //指向busdrvier容器

       error= kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,

                                 "%s", drv->name);      //驅動的kobject初始化和添加dirsysfs中,詳見標註三

       if(error)

              gotoout_unregister;

 

       klist_add_tail(&priv->knode_bus,&bus->p->klist_drivers);              //初始化busnode鏈表並添加klist_driver到末尾

       if(drv->bus->p->drivers_autoprobe) {        //drivers_autoprobe其值爲1bus註冊的時候設定

              error= driver_attach(drv);

              if(error)

                     gotoout_unregister;

       }

       module_add_driver(drv->owner,drv);  //添加drvmodule 標註六

 

       error= driver_create_file(drv, &driver_attr_uevent);  //sysfs的目錄下創建文件uevent屬性文件,見標註七

       if(error) {

              printk(KERN_ERR"%s: uevent attr (%s) failed\n",

                     __func__,drv->name);

       }

       error= driver_add_attrs(bus, drv);      //driver添加bus上的所有屬性

       if(error) {

              /*How the hell do we get out of this pickle? Give up */

              printk(KERN_ERR"%s: driver_add_attrs(%s) failed\n",

                     __func__,drv->name);

       }

 

       if(!drv->suppress_bind_attrs) {

              error= add_bind_files(drv);         //添加綁定文件,driver_attr_bind driver_attr_unbind見標註七

              if(error) {

                     /*Ditto */

                     printk(KERN_ERR"%s: add_bind_files(%s) failed\n",

                            __func__,drv->name);

              }

       }

 

       kobject_uevent(&priv->kobj,KOBJ_ADD);              //產生一個KOBJ_ADD uevent

       return0;

 

out_unregister:

       kobject_put(&priv->kobj);

       kfree(drv->p);

       drv->p= NULL;

out_put_bus:

       bus_put(bus);

       returnerror;

}

標註三:

int kobject_init_and_add(struct kobject*kobj, struct kobj_type *ktype,

                      struct kobject *parent, const char *fmt, ...)

{

       va_listargs;

       intretval;

 

       kobject_init(kobj,ktype);      //初始化kobject

 

       va_start(args,fmt);        //動態可變參數的使用

       retval= kobject_add_varg(kobj, parent, fmt, args);     //函數包含的操作kobject_set_name_vargs(kobj, fmt, vargs)設置kobject kobject_add_internal(kobj)

       va_end(args);

 

       returnretval;

}

static intkobject_add_varg(struct kobject *kobj, struct kobject *parent,

                         constchar *fmt, va_list vargs)

{

       intretval;

 

       retval= kobject_set_name_vargs(kobj, fmt, vargs);     //主要是將vargs按照fmt格式給kobject起個名字,從調用關係知道vargsdrv->name,也就是驅動的名字

       if(retval) {

              printk(KERN_ERR"kobject: can not set name properly!\n");

              returnretval;

       }

       kobj->parent= parent;

       returnkobject_add_internal(kobj);

}

static intkobject_add_internal(struct kobject *kobj)    //這個函數主要設置drvierkobjectbus之間的層次關係,然後在sysfs中建立該驅動的文件夾

{

       interror = 0;

       structkobject *parent;

 

       if(!kobj)

              return-ENOENT;

 

       if(!kobj->name || !kobj->name[0]) {

              WARN(1,"kobject: (%p): attempted to be registered with empty "

                      "name!\n", kobj);

              return-EINVAL;

       }

 

       parent= kobject_get(kobj->parent);     //得到父節點,從上面知道parentNULL

 

       /*join kset if set, use it as parent if we do not already have one */

       if(kobj->kset) {     //kset不爲空

              if(!parent)     //parent爲空

                     parent= kobject_get(&kobj->kset->kobj);

              kobj_kset_join(kobj);

              kobj->parent= parent;

/*如果kset不爲空,而parent爲空(這裏這個條件一定成立的,因爲kset=bus->p->drivers_ksetparent=NULL)
則該kobj->parent指向kobj->kset->kobj,而且將kobj加入到kobj->ksetlist中,也就是driver放入buskset列表中,也就是busdriver的容器,實際上bus同時還是device的容器,當然bus本身實質上也是個kobject,所以理解kset這個容器的概念至關重要,它是構成了sysfs的層次結構關係*/

       }

 

       pr_debug("kobject:'%s' (%p): %s: parent: '%s', set: '%s'\n",

               kobject_name(kobj), kobj, __func__,

               parent ? kobject_name(parent) :"<NULL>",

               kobj->kset ?kobject_name(&kobj->kset->kobj) : "<NULL>");

 

       error= create_dir(kobj);              //建立該驅動的文件夾

       if(error) {

              kobj_kset_leave(kobj);

              kobject_put(parent);

              kobj->parent= NULL;

 

              /*be noisy on error issues */

              if(error == -EEXIST)

                     WARN(1,"%s failed for %s with "

                          "-EEXIST, don't try to registerthings with "

                          "the same name in the samedirectory.\n",

                          __func__, kobject_name(kobj));

              else

                     WARN(1,"%s failed for %s (error: %d parent: %s)\n",

                          __func__, kobject_name(kobj), error,

                          parent ? kobject_name(parent) :"'none'");

       }else

              kobj->state_in_sysfs= 1;

 

       returnerror;

}

標註三end

int driver_attach(structdevice_driver *drv)

{

       returnbus_for_each_dev(drv->bus, NULL, drv,__driver_attach);

}

intbus_for_each_dev(struct bus_type *bus, struct device *start,

                   void *data,int (*fn)(struct device *, void *))

{

       structklist_iter i;

       structdevice *dev;

       interror = 0;

 

       if(!bus)

              return-EINVAL;

 

       klist_iter_init_node(&bus->p->klist_devices,&i,

                          (start ? &start->p->knode_bus :NULL));   //bus中的已註冊的device列表放到迭代器中,方便索引

       while((dev = next_device(&i)) && !error)  //將驅動逐個地與列表中每一個的device匹配,可能一個驅動匹配好幾個設備

              error= fn(dev, data);     //這個fn就是上面傳下來的__driver_attach

       klist_iter_exit(&i);

       returnerror;

}

static int__driver_attach(struct device *dev, void *data)

{

       structdevice_driver *drv = data;

 

       /*

        * Lock device and try to bind to it. We dropthe error

        * here and always return 0, because we need tokeep trying

        * to bind to devices and some drivers willreturn an error

        * simply if it didn't support the device.

        *

        * driver_probe_device() will spit a warning ifthere

        * is an error.

        */

 

       if(!driver_match_device(drv, dev))      //driver嘗試與device匹配 詳見標註四

              return0;

 

       if(dev->parent)     /* Needed for USB */

              device_lock(dev->parent);

       device_lock(dev);

       if(!dev->driver)    //如果設備沒有指定driver

              driver_probe_device(drv,dev);     //那麼需要初始化匹配到的這個設備attempt to bind device & driver together 詳見標註五

       device_unlock(dev);

       if(dev->parent)

              device_unlock(dev->parent);

 

       return0;

}

標註四:

static inline intdriver_match_device(struct device_driver *drv,

                                  struct device *dev)

{

       returndrv->bus->match ? drv->bus->match(dev, drv) : 1;

}

這裏看bus的總線的match函數是否已經註冊,如果沒註冊則直接返回1直接成功,如果註冊,則調用註冊的匹配函數。match通常實現爲首先掃描driver支持的id設備表,如果爲NULL就用名字進行匹配

i2c總線爲例:

structbus_type i2c_bus_type = {
.name = "i2c",
.dev_attrs = i2c_dev_attrs,
.match = i2c_device_match,
...
};
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(drv);

/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;//
只匹配id的名字和client的名字,跟驅動的名字沒有關係,注意這裏的client是設備轉換過來,而不是設備的本身

return 0;
}
轉而調用i2c_match_id();
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
const struct i2c_client *client)
{
while (id->name[0]) {
if (strcmp(client->name, id->name) == 0) //
匹配設備client名字和id_table中的名字
return id;
id++;
}
return NULL;
}
所以i2c總線根據設備client名字和id_table中的名字進行匹配的。如果匹配了,則返回id值,在i2c_device_match中則返回真。也就是busmatch函數將會返回真。那將會進入driver_probe_device()
4-2-1-1-2
driver_probe_device()
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;

if (!device_is_registered(dev)) //
首先判斷這個device是否已經註冊
return -ENODEV;

pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);

ret = really_probe(dev, drv); //
轉而調用really_probe()

return ret;
}

4-2-1-1-2-1,really_probe()

static atomic_t probe_count = ATOMIC_INIT(0); //
記錄probe數目
static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); //probe
隊列

static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;

atomic_inc(&probe_count); //
原子增加計數
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));

dev->driver = drv; //
把驅動賦值給dev->drvier
if (driver_sysfs_add(dev)) { //
主要是添加driverdev之間的連接文件,見4-2-1-1-2-1-1分析
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}

if (dev->bus->probe) { //
如果busprobe註冊將執行,否則執行driverprobe,這也是函數開始時檢測的原因!
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}

driver_bound(dev); //driver
綁定dev,見4-2-1-1-2-1-2分析
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;

probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;

if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
4-2-1-1-2-1-1
driver_sysfs_add
static int driver_sysfs_add(struct device *dev)
{
int ret;

ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
kobject_name(&dev->kobj)); //
driver目錄下添加以dev->kobj名字的連接文件,連接到device
if (ret == 0) {
ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
"driver"); //
同樣在device目錄下添加‘driver’爲名字的連接文件連接到drvier
if (ret)
sysfs_remove_link(&dev->driver->p->kobj,
kobject_name(&dev->kobj));
}
return ret;
}
4-2-1-1-2-1-2
driver_bound()
static void driver_bound(struct device *dev)
{
if (klist_node_attached(&dev->p->knode_driver)) { //
查看是否已經綁定
printk(KERN_WARNING "%s: device %s already bound\n",
__func__, kobject_name(&dev->kobj));
return;
}

pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
__func__, dev->driver->name);

if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev); //
調用註冊bus通知鏈上的所有函數

klist_add_tail(&dev->p->knode_driver,&dev->driver->p->klist_devices); //
將設備的驅動node添加到diverklist_devices.
}

標註四end

標註五:

intdriver_probe_device(struct device_driver *drv, struct device *dev)

{

       int ret = 0;

 

       if (!device_is_registered(dev))

              return -ENODEV;

 

       pr_debug("bus: '%s': %s: matched device %s with driver%s\n",

               drv->bus->name, __func__, dev_name(dev),drv->name);

 

       pm_runtime_get_noresume(dev);

       pm_runtime_barrier(dev);

       ret = really_probe(dev, drv);

       pm_runtime_put_sync(dev);

 

       return ret;

}

static inline int device_is_registered(structdevice *dev)

{

       returndev->kobj.state_in_sysfs;    // sysfs中表示已經註冊

}

static int really_probe(structdevice *dev, struct device_driver *drv)

{

       intret = 0;

 

       atomic_inc(&probe_count);

       pr_debug("bus:'%s': %s: probing driver %s with device %s\n",

               drv->bus->name, __func__, drv->name,dev_name(dev));

       WARN_ON(!list_empty(&dev->devres_head));

 

       dev->driver= drv;  // devicedriver初始化成該driver

 

       /*If using pinctrl, bind pins now before probing */

       ret= pinctrl_bind_pins(dev);

       if(ret)

              gotoprobe_failed;

 

       if(driver_sysfs_add(dev)) {

              printk(KERN_ERR"%s: driver_sysfs_add(%s) failed\n",

                     __func__,dev_name(dev));

              gotoprobe_failed;

       }

                                                 //利用probe初始化設備

       if(dev->bus->probe) {         //如果busprobe存在就用bus

              ret= dev->bus->probe(dev);

              if(ret)

                     gotoprobe_failed;

       }else if (drv->probe) {         //如果bus的不存在driver的存在再用driver

              ret= drv->probe(dev);

              if(ret)

                     gotoprobe_failed;

       }

 

       driver_bound(dev);        //調用driver_bound進行綁定

       ret= 1;

       pr_debug("bus:'%s': %s: bound device %s to driver %s\n",

               drv->bus->name, __func__, dev_name(dev),drv->name);

       gotodone;

 

probe_failed:

       devres_release_all(dev);

       driver_sysfs_remove(dev);

       dev->driver= NULL;

 

       if(ret == -EPROBE_DEFER) {

              /*Driver requested deferred probing */

              dev_info(dev,"Driver %s requests probe deferral\n", drv->name);

              driver_deferred_probe_add(dev);

       }else if (ret != -ENODEV && ret != -ENXIO) {

              /*driver matched but the probe failed */

              printk(KERN_WARNING

                     "%s: probe of %s failed with error%d\n",

                     drv->name, dev_name(dev), ret);

       }else {

              pr_debug("%s:probe of %s rejects match %d\n",

                     drv->name, dev_name(dev), ret);

       }

       /*

        * Ignore errors returned by ->probe so thatthe next driver can try

        * its luck.

        */

       ret= 0;

done:

       atomic_dec(&probe_count);

       wake_up(&probe_waitqueue);

       returnret;

}

static void driver_bound(structdevice *dev)

{

       if(klist_node_attached(&dev->p->knode_driver)) {    //判斷是否已經綁定

              printk(KERN_WARNING"%s: device %s already bound\n",

                     __func__,kobject_name(&dev->kobj));

              return;

       }

 

       pr_debug("driver:'%s': %s: bound to device '%s'\n", dev_name(dev),

               __func__, dev->driver->name);

 

       klist_add_tail(&dev->p->knode_driver,&dev->driver->p->klist_devices);              //將設備添加到driver的鏈表

 

       /*

        * Make sure the device is no longer in one ofthe deferred lists and

        * kick off retrying all pending devices

        */

       driver_deferred_probe_del(dev);

       driver_deferred_probe_trigger();

 

       if(dev->bus)

              blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

                                        BUS_NOTIFY_BOUND_DRIVER, dev);

}

標註五end

標註六:

void module_add_driver(struct module *mod,struct device_driver *drv)

{

       char*driver_name;

       intno_warn;

       structmodule_kobject *mk = NULL;

 

       if(!drv)

              return;

 

       if(mod)         //一般情況下爲THIS_MODULE

              mk= &mod->mkobj;

       elseif (drv->mod_name) {    //如果沒模塊,則檢查驅動的模塊名

              structkobject *mkobj;

 

              /*Lookup built-in module entry in /sys/modules */

              mkobj= kset_find_obj(module_kset, drv->mod_name);     //根據驅動模塊的名字去module_kset集合中找

              if(mkobj) {

                     mk= container_of(mkobj, struct module_kobject, kobj);    //container_of方法通過kobj轉換成module_kobject

                     /*remember our module structure */

                     drv->p->mkobj= mk;    //賦值給驅動的mkobj

                     /*kset_find_obj took a reference */

                     kobject_put(mkobj);

              }

       }

 

       if(!mk)          //mk如果爲null則返回

              return;

 

       /*Don't check return codes; these calls are idempotent */

       no_warn= sysfs_create_link(&drv->p->kobj, &mk->kobj,"module");     //在驅動文件夾下創建名爲‘module’的鏈接文件,鏈接到module文件夾

       driver_name= make_driver_name(drv);      //生成driver_name,module

       if(driver_name) {

              module_create_drivers_dir(mk);   //在具體的module文件夾下創建driver目錄

              no_warn= sysfs_create_link(mk->drivers_dir, &drv->p->kobj,

                                       driver_name);        //在上面創建的driver目錄下,生成一個名爲driver_name指定的鏈接文件,鏈接到驅動的文件夾

              kfree(driver_name);

       }

}

static char *make_driver_name(structdevice_driver *drv)  //這個函數的功能就是生成一個名字,這個有bus和驅動的名字組成

{

       char*driver_name;

 

       driver_name= kasprintf(GFP_KERNEL, "%s:%s", drv->bus->name, drv->name);  申請內存並將bus的名字和驅動的名字組成一塊,中間加一個冒號

       if(!driver_name)

              returnNULL;

 

       returndriver_name;

}

標註六end

 

標註七:

/**

 *driver_create_file - create sysfs file for driver.

 *@drv: driver.

 *@attr: driver attribute descriptor.

 */

int driver_create_file(struct device_driver*drv,

                     const struct driver_attribute *attr)

{

       interror;

       if(drv)

              error= sysfs_create_file(&drv->p->kobj, &attr->attr);

       else

              error= -EINVAL;

       returnerror;

}

static int driver_add_attrs(struct bus_type*bus, struct device_driver *drv)

{

       interror = 0;

       inti;

 

       if(bus->drv_attrs) {

              for(i = 0; attr_name(bus->drv_attrs[i]); i++) {

                     error= driver_create_file(drv, &bus->drv_attrs[i]);

                     if(error)

                            gotoerr;

              }

       }

done:

       returnerror;

err:

       while(--i >= 0)

              driver_remove_file(drv,&bus->drv_attrs[i]);

       gotodone;

}

static int __must_checkadd_bind_files(struct device_driver *drv)

{

       intret;

 

       ret= driver_create_file(drv, &driver_attr_unbind);

       if(ret == 0) {

              ret= driver_create_file(drv, &driver_attr_bind);

              if(ret)

                     driver_remove_file(drv,&driver_attr_unbind);

       }

       returnret;

}

標註七end

 

 

總結一下,driver的註冊,主要涉及將自身掛接到busdriver鏈表,並將匹配到的設備加入自己的device鏈表,並且將匹配到的devicedriver成員初始化爲該driver,私有屬性的driver節點也掛到driver的設備鏈表下,其中匹配函數是利用利用busmatch函數,該函數通常判斷如果driverid表,就查表匹配,如果沒有就用driverdevice名字匹配。當匹配成功後如果自動初始化標誌允許則調用初始化函數probebusprobe優先級始終高於driver的。另外注意一點driver是沒有總的起始端點的,driver不是可具體描述的事物。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章