Linux设备驱动模型探究--4(driver)



四. 关于驱动(driver)--driver.c

/*数据结构*/
struct device_driver {
 const char  *name;  /*驱动名字*/
 struct bus_type  *bus; /*驱动所属总线*/
 struct module  *owner; /*驱动所在内核模块*/

 int (*probe) (struct device *dev);  /*当总线bus将该驱动和对应得设备相互绑定的时候,
           /*内核会首先调用bus的probe函数,如果没有就会调用该probe函数,在driver_register中调用*/
           
 int (*remove) (struct device *dev);  /*原理和probe一样, 但是在driver_unregister中调用*/

 struct driver_private *p;
};


驱动上主要的操作:

/*在bus的drivers_kset集合查找驱动,name-查找名称,bus-哪个总线*/-->在bus上查找名称为name的驱动,成功返回driver
struct device_driver *driver_find(const char *name, struct bus_type *bus)
{
 struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
 struct driver_private *priv;

 if (k) {
  priv = to_driver(k);
  return priv->driver;
 }
 return NULL;
}

/**
 * driver_register - register driver with bus
 * @drv: driver to register
 *
 * We pass 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)
{
 int ret;
 struct device_driver *other;
 if ((drv->bus->probe && drv->probe) ||
     (drv->bus->remove && drv->remove) ||
     (drv->bus->shutdown && drv->shutdown))
  printk(KERN_WARNING "Driver '%s' needs updating - please use "
   "bus_type methods\n", drv->name);

 other = driver_find(drv->name, drv->bus);  /*先判断驱动是否注册了*/
 if (other) {
  put_driver(other);
  printk(KERN_ERR "Error: Driver '%s' is already registered, "
   "aborting...\n", drv->name);
  return -EBUSY;
 }

 ret = bus_add_driver(drv);   /*往bus上注册(添加)驱动*/
 if (ret)
  return ret;
 ret = driver_add_groups(drv, drv->groups);
 if (ret)
  bus_remove_driver(drv);
 return ret;
}

扫描二维码关注公众号,回复: 5317683 查看本文章


***********************接下分析bus_add_driver()****************************

/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
 struct bus_type *bus;
 struct driver_private *priv;
 int error = 0;

 bus = bus_get(drv->bus);
 if (!bus)
  return -EINVAL;

 /*初始化驱动私有数据 p*/
 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 if (!priv) {
  error = -ENOMEM;
  goto out_put_bus;
 }
 
 klist_init(&priv->klist_devices, NULL, NULL);
 priv->driver = drv;
 drv->p = priv;
 
 /*建立priv->kobj和bus->p->drivers_kset(扮演parent)层次关系,*/
 priv->kobj.kset = bus->p->drivers_kset;
 
 error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
         "%s", drv->name);

 if (drv->bus->p->drivers_autoprobe) {
  error = driver_attach(drv);   //匹配设备
  if (error)
   goto out_unregister;
 }
 
 klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);//向bus驱动链表中添加驱动
 module_add_driver(drv->owner, drv);  //向模块中添加驱动

 error = driver_create_file(drv, &driver_attr_uevent); //创建uevent属性文件

 error = driver_add_attrs(bus, drv);      //创先驱动属性文件


 /* * kobject_uevent - notify userspace by sending an uevent
  *
  * @action: action that is happening
  * @kobj: struct kobject that the action is happening to
  *
  */
 kobject_uevent(&priv->kobj, KOBJ_ADD);    
 return 0;
}

/*参考资料:

深入Linux设备驱动程序内核机制。 陈雪松著

Linux设备驱动开发详解--基于最新的Linux4.0内核。 宋宝华著

*/

猜你喜欢

转载自blog.csdn.net/jun_8018/article/details/77581411
今日推荐