Linux设备驱动模型-Driver

前言

linux将所有的驱动抽象为struct device_driver结构。这样设计可以方便驱动程序更好编写,在编写驱动的时候只需要将此结构嵌入到具体的驱动中即可。
比如常见的结构:  struct platform_driver结构
struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
	bool prevent_deferred_probe;
};
可以看到device_driver结构嵌入到platform_driver

数据结构

struct device_driver {
	const char		*name;
	struct bus_type		*bus;

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

	const struct of_device_id	*of_match_table;
	const struct acpi_device_id	*acpi_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);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};

name:   设备驱动的名称
bus:    设备驱动所属的总线
owner:  设备驱动的owner,通常为THIS_MODULE
suppress_bind_attrs:  通过sysfs操作设备驱动的bind/unbind,用来使能/关闭设备与驱动的自动匹配
of_device_id:  device_tree中使用,用于匹配设备。
probe,remove: 当设备匹配/移除的时候,会调用设备驱动的probe/remove函数。
shutdown,suspend, resume:  代表设备驱动在调用管理的时候的回调函数。
groups:  设备驱动的属性。
p:           设备驱动的私有数据结构,通常可以将驱动的信息放入此结构中。

内核使用driver_attribute结构代表设备驱动的属性
struct driver_attribute {
	struct attribute attr;
	ssize_t (*show)(struct device_driver *driver, char *buf);
	ssize_t (*store)(struct device_driver *driver, const char *buf,
			 size_t count);
};
设备驱动的属性,同样通过注册,最后调用到驱动的show和store函数。

和设备一样,内核也为设备驱动定义了一些驱动的宏属性,方便定义驱动属性。
#define DRIVER_ATTR(_name, _mode, _show, _store) \
	struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DRIVER_ATTR_RW(_name) \
	struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
#define DRIVER_ATTR_RO(_name) \
	struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
#define DRIVER_ATTR_WO(_name) \
	struct driver_attribute driver_attr_##_name = __ATTR_WO(_name)

设备驱动相关函数

  • driver_register(注册一个驱动到系统)
int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	BUG_ON(!drv->bus->p);                               //确定bus->p是否存在,不存在则会产生panic

	if ((drv->bus->probe && drv->probe) ||              //警告信息,有新驱动的时候出出现此log。
	    (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) {
		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;
	}
	kobject_uevent(&drv->p->kobj, KOBJ_ADD);           //使用uevent机制,通知上层添加新的驱动

	return ret;
}
A:  通过驱动的名称在所属的总线上查找,判断总线上是否已经有此驱动,防止重复注册。
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) {
		/* Drop reference added by kset_find_obj() */
		kobject_put(k);
		priv = to_driver(k);
		return priv->driver;
	}
	return NULL;
}
通过kset_find_obj函数,在drivers_set中查找是否已经注册,已经注册返回具体的驱动,如果没有注册返回NULL。

B:   将具体的驱动添加到所属的总线,这是注册驱动的核心函数。
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;

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

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);       //申请driver_private内存
	if (!priv) {
		error = -ENOMEM;
		goto out_put_bus;
	}
	klist_init(&priv->klist_devices, NULL, NULL);                     
	priv->driver = drv;                               //将驱动存放到driver_private的driver中
	drv->p = priv;                                    //存放priv到device_driver的p中
	priv->kobj.kset = bus->p->drivers_kset;           //设置kset
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,              
				     "%s", drv->name);     //初始化和添加一个kobject
	if (error)
		goto out_unregister;

	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);   //添加驱动到klist_driver链表中
	if (drv->bus->p->drivers_autoprobe) {                       //驱动所属的bus是否支持自动probe
		error = driver_attach(drv);                         //如果支持,则调用attach函数,这个函数在device中已经分析过
		if (error)
			goto out_unregister;
	}
	module_add_driver(drv->owner, drv);                        

	error = driver_create_file(drv, &driver_attr_uevent);         //创建驱动的Uevent属性
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
			__func__, drv->name);
	}
	error = driver_add_groups(drv, bus->drv_groups);             //创建bus下的驱动属性
	if (error) {
		/* How the hell do we get out of this pickle? Give up */
		printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
			__func__, drv->name);
	}

	if (!drv->suppress_bind_attrs) {                   //添加绑定/不绑定的属性
		error = add_bind_files(drv);
		if (error) {
			/* Ditto */
			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
				__func__, drv->name);
		}
	}

	return 0;
}
  • driver_unregister(从系统中移除一个驱动)
void driver_unregister(struct device_driver *drv)
{
	if (!drv || !drv->p) {
		WARN(1, "Unexpected driver unregister!\n");
		return;
	}
	driver_remove_groups(drv, drv->groups);        //移除驱动的属性
	bus_remove_driver(drv);                        //从所属的bus下移除该驱动
}
void bus_remove_driver(struct device_driver *drv)
{
	if (!drv->bus)
		return;

	if (!drv->suppress_bind_attrs)     //移除bind/unbind的属性
		remove_bind_files(drv);
	driver_remove_groups(drv, drv->bus->drv_groups); //移除设备属性
	driver_remove_file(drv, &driver_attr_uevent);    //移除uevent属性
	klist_remove(&drv->p->knode_bus);                //移除驱动节点,从klist_driver链表中
	pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
	driver_detach(drv);                              //解除设备与驱动联系
	module_remove_driver(drv);
	kobject_put(&drv->p->kobj);                      //驱动引用计数减1
	bus_put(drv->bus);                               //总线引用计数减1
}
重点看下设备与对应的驱动是如何解除联系的。
void driver_detach(struct device_driver *drv)
{
	struct device_private *dev_prv;
	struct device *dev;

	for (;;) {
		spin_lock(&drv->p->klist_devices.k_lock);              //加锁,防止别的驱动也在做相似的操作
		if (list_empty(&drv->p->klist_devices.k_list)) {       //如果设备链表为空,直接返回
			spin_unlock(&drv->p->klist_devices.k_lock);
			break;
		}
		dev_prv = list_entry(drv->p->klist_devices.k_list.prev,  //对设备链表中的每个设备,调用__device_release_drive函数
				     struct device_private,
				     knode_driver.n_node);
		dev = dev_prv->device;
		get_device(dev);
		spin_unlock(&drv->p->klist_devices.k_lock);

		if (dev->parent)	/* Needed for USB */
			device_lock(dev->parent);
		device_lock(dev);
		if (dev->driver == drv)
			__device_release_driver(dev);
		device_unlock(dev);
		if (dev->parent)
			device_unlock(dev->parent);
		put_device(dev);
	}
}
接下来分析__device_release_driver函数
static void __device_release_driver(struct device *dev)
{
	struct device_driver *drv;

	drv = dev->driver;
	if (drv) {
		pm_runtime_get_sync(dev);    

		driver_sysfs_remove(dev);     //从sysfs中移除该驱动的信息

		if (dev->bus)                 //调用bus下的通知机制,发送unbind_driver消息
			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
						     BUS_NOTIFY_UNBIND_DRIVER,
						     dev);

		pm_runtime_put_sync(dev);

		if (dev->bus && dev->bus->remove)
			dev->bus->remove(dev);          //调用bus下的remove函数
		else if (drv->remove)                   //调用该驱动的remove函数
			drv->remove(dev);
		devres_release_all(dev);               //释放该设备所占用的资源
		dev->driver = NULL;
		dev_set_drvdata(dev, NULL);
		klist_remove(&dev->p->knode_driver);     
		if (dev->bus)
			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
						     BUS_NOTIFY_UNBOUND_DRIVER,
						     dev);

	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值