总线、设备、驱动、类 .

分类: linux设备驱动 353人阅读 评论(0) 收藏 举报

一. 总线、设备、驱动、类各自的相关结构体

    1.总线

     1.1 总线类型结构体

struct bus_type {
	const char	*name;	//总线类型名
	struct bus_attribute	*bus_attrs;	//总线属性
	struct device_attribute	*dev_attrs;	//设备属性
	struct driver_attribute	*drv_attrs;	//驱动属性
	int (*match)(struct device *dev, struct device_driver *drv);	//match方法
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);	//uevent方法
	int (*probe)(struct device *dev);		//总线probe方法
	int (*remove)(struct device *dev);		//总线remove方法
	void (*shutdown)(struct device *dev);	//总线remove方法
	int (*suspend)(struct device *dev, pm_message_t state);	//总线shutdown方法
	int (*resume)(struct device *dev);		//总线resume方法
	const struct dev_pm_ops *pm;	//总线电源管理函数集
	struct bus_type_private *p;		//总线私有数据
};

    1.2 总线私有数据结构体

struct bus_type_private {
	struct kset subsys;
	struct kset *drivers_kset;
	struct kset *devices_kset;
	struct klist klist_devices;
	struct klist klist_drivers;
	struct blocking_notifier_head bus_notifier;
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;
};

     1.3 总线类型属性结构体

struct bus_attribute {
	struct attribute	attr;
	ssize_t (*show)(struct bus_type *bus, char *buf);
	ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);
};

     1.4 设备属性结构体

struct device_attribute {
	struct attribute	attr;
	ssize_t (*show)(struct device *dev, struct device_attribute *attr,char *buf);
	ssize_t (*store)(struct device *dev, struct device_attribute *attr,const char *buf, size_t count);
};

     1.5 设备驱动属性结构体

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

 

     2.设备

     2.1 设备结构体

struct device {
	struct device	*parent;	//父设备指针
	struct device_private	*p;	//设备私有数据
	struct kobject kobj;
	const char	*init_name; /* initial name of the device */
	struct device_type	*type;
	struct mutex	mutex;
	struct bus_type	*bus;	/* type of bus device is on */
	struct device_driver *driver;	//匹配的设备驱动
	void	*platform_data;	//平台数据	
	struct dev_pm_info	power;
#ifdef CONFIG_NUMA
	int	numa_node;/* NUMA node this device is close to */
#endif
	u64	*dma_mask;/* dma mask (if dma'able device) */
	u64	coherent_dma_mask;
	struct device_dma_parameters *dma_parms;
	struct list_head	dma_pools;	/* dma pools (if dma'ble) */
	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem override */
	/* arch specific additions */
	struct dev_archdata	archdata;
#ifdef CONFIG_OF
	struct device_node	*of_node;
#endif
	dev_t	devt;	//设备号
	spinlock_t	devres_lock;
	struct list_head	devres_head;
	struct klist_node	knode_class;
	struct class	*class;	//对应的设备类
	const struct attribute_group **groups;	/* optional groups */
	void	(*release)(struct device *dev);	//release方法
};

     2.2 设备私有数据结构体

struct device_private {
	struct klist klist_children;
	struct klist_node knode_parent;
	struct klist_node knode_driver;
	struct klist_node knode_bus;
	void *driver_data;
	struct device *device;
};

 

     3.驱动

     3.1 设备驱动结构体

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 */
#if defined(CONFIG_OF)
	const struct of_device_id	*of_match_table;
#endif
	int (*probe) (struct device *dev);	//probe方法
	int (*remove) (struct device *dev);	//remove方法
	void (*shutdown) (struct device *dev);	//shutdown方法
	int (*suspend) (struct device *dev, pm_message_t state);	//suspend方法
	int (*resume) (struct device *dev);	//resume方法
	const struct attribute_group **groups;
	const struct dev_pm_ops *pm;	//电源管理函数集
	struct driver_private *p;	//设备驱动私有数据
};

     3.2 设备驱动私有数据结构体

struct driver_private {
	struct kobject kobj;
	struct klist klist_devices;
	struct klist_node knode_bus;
	struct module_kobject *mkobj;
	struct device_driver *driver;
};

 

     4.

     4.1 设备类结构体

struct class {
	const char	*name;	//类名
	struct module	*owner;	//模块所有者
	struct class_attribute	*class_attrs;	//类属性
	struct device_attribute	*dev_attrs;	//设备属性
	struct kobject	*dev_kobj;
	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
	char *(*devnode)(struct device *dev, mode_t *mode);
	void (*class_release)(struct class *class);
	void (*dev_release)(struct device *dev);
	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);
	const struct kobj_ns_type_operations *ns_type;
	const void *(*namespace)(struct device *dev);
	const struct dev_pm_ops *pm;	//电源管理函数集
	struct class_private *p;	//类私有数据结构
};

     4.2 类属私有数据结构体

struct class_private {
	struct kset class_subsys;
	struct klist class_devices;
	struct list_head class_interfaces;
	struct kset class_dirs;
	struct mutex class_mutex;
	struct class *class;
};

     4.3 类属性结构体

struct class_attribute {
	struct attribute attr;
	ssize_t (*show)(struct class *class, struct class_attribute *attr,char *buf);
	ssize_t (*store)(struct class *class, struct class_attribute *attr,const char *buf, size_t count);
};


二. 初始化过程

     1 系统启动过程中调用start_kernel函数->rest_init()->创建kernel_init线程->do_basic_setup()->driver_init()

     2.driver_init

void __init driver_init(void)
{
	devtmpfs_init();		//初始化devtmpfs文件系统
	devices_init();		//设备初始化
	buses_init();		//总线初始化
	classes_init();		//设备类初始化
	firmware_init();
	hypervisor_init();
	platform_bus_init();
	system_bus_init();
	cpu_dev_init();
	memory_dev_init();
}

     3. devices_init

int __init devices_init(void)
{
	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);	//创建"/sys/devices"
	if (!devices_kset)
		return -ENOMEM;
	dev_kobj = kobject_create_and_add("dev", NULL);	//创建"/sys/dev"
	if (!dev_kobj)
		goto dev_kobj_err;
	sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);	//创建"/sys/dev/block"
	if (!sysfs_dev_block_kobj)
		goto block_kobj_err;
	sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);		//创建"/sys/dev/char"
	if (!sysfs_dev_char_kobj)
		goto char_kobj_err;
	return 0;

 char_kobj_err:
	kobject_put(sysfs_dev_block_kobj);
 block_kobj_err:
	kobject_put(dev_kobj);
 dev_kobj_err:
	kset_unregister(devices_kset);
	return -ENOMEM;
}

     4. buses_init

int __init buses_init(void)
{
	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);	//创建"/sys/bus"
	if (!bus_kset)
		return -ENOMEM;
	return 0;
}

    5. classes_init

int __init classes_init(void)
{
	class_kset = kset_create_and_add("class", NULL, NULL);		//创建"/sys/class"
	if (!class_kset)
		return -ENOMEM;
	return 0;
}

 

     6.经过上面的初始化得到一些全局的变量

bus_kset --> /sys/bus
class_kset --> /sys/class
devices_kset --> /sys/devices
dev_kobj--> /sys/dev
sysfs_dev_block_kobj --> /sys/dev/block
sysfs_dev_char_kobj --> /sys/dev/char


三. 总线 设备 驱动 类 的注册与注销

     1. 总线注册与注销

     1.1 注册

int bus_register(struct bus_type *bus)
{
	int retval;
	struct bus_type_private *priv;

	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);	//分配总线类型私有数据结构体
	if (!priv)
		return -ENOMEM;

	priv->bus = bus;		//私有数据结构体的总线指针指向总线
	bus->p = priv;		//总线的私有数据指针指向私有数据结构体

	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);	//初始化通知链表头

	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
	if (retval)
		goto out;

	priv->subsys.kobj.kset = bus_kset;		//bus_kset --> /sys/bus
        priv->subsys.kobj.ktype = &bus_ktype;
	priv->drivers_autoprobe = 1;

	retval = kset_register(&priv->subsys);	//创建"/sys/bus/xxx"
	if (retval)
		goto out;

	retval = bus_create_file(bus, &bus_attr_uevent);
	if (retval)
		goto bus_uevent_fail;

	priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);	//创建"/sys/bus/xxx/devices"
	if (!priv->devices_kset) {
		retval = -ENOMEM;
		goto bus_devices_fail;
	}

	priv->drivers_kset = kset_create_and_add("drivers", NULL,&priv->subsys.kobj);	//创建"/sys/bus/xxx/drivers"
	if (!priv->drivers_kset) {
		retval = -ENOMEM;
		goto bus_drivers_fail;
	}

	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
	klist_init(&priv->klist_drivers, NULL, NULL);

	retval = add_probe_files(bus);
	if (retval)
		goto bus_probe_files_fail;

	retval = bus_add_attrs(bus);
	if (retval)
		goto bus_attrs_fail;

	pr_debug("bus: '%s': registered\n", bus->name);
	return 0;

bus_attrs_fail:
	remove_probe_files(bus);
bus_probe_files_fail:
	kset_unregister(bus->p->drivers_kset);
bus_drivers_fail:
	kset_unregister(bus->p->devices_kset);
bus_devices_fail:
	bus_remove_file(bus, &bus_attr_uevent);
bus_uevent_fail:
	kset_unregister(&bus->p->subsys);
out:
	kfree(bus->p);
	bus->p = NULL;
	return retval;
}


     1.2 注销

void bus_unregister(struct bus_type *bus)
{
	pr_debug("bus: '%s': unregistering\n", bus->name);
	bus_remove_attrs(bus);
	remove_probe_files(bus);
	kset_unregister(bus->p->drivers_kset);
	kset_unregister(bus->p->devices_kset);
	bus_remove_file(bus, &bus_attr_uevent);
	kset_unregister(&bus->p->subsys);
	kfree(bus->p);
	bus->p = NULL;
}

 

     2.设备注册与注销

     2.1 注册

int device_register(struct device *dev)
{
	device_initialize(dev);
	return device_add(dev);
}

     2.1.1 device_initialize

void device_initialize(struct device *dev)
{
	dev->kobj.kset = devices_kset;    //devices_kset --> /sys/devices	
        	kobject_init(&dev->kobj, &device_ktype);
	INIT_LIST_HEAD(&dev->dma_pools);
	mutex_init(&dev->mutex);
	lockdep_set_novalidate_class(&dev->mutex);
	spin_lock_init(&dev->devres_lock);
	INIT_LIST_HEAD(&dev->devres_head);
	device_pm_init(dev);
	set_dev_node(dev, -1);
}

     2.1.2 device_add

int device_add(struct device *dev)
{
	struct device *parent = NULL;
	struct class_interface *class_intf;
	int error = -EINVAL;
	dev = get_device(dev);
	if (!dev)
		goto done;

	if (!dev->p) {
		error = device_private_init(dev);
		if (error)
			goto done;
	}

	if (dev->init_name) {
		dev_set_name(dev, "%s", dev->init_name);
		dev->init_name = NULL;
	}

	if (!dev_name(dev)) {
		error = -EINVAL;
		goto name_error;
	}

	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
	parent = get_device(dev->parent);
	setup_parent(dev, parent);
	if (parent)
		set_dev_node(dev, dev_to_node(parent));
	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
	if (error)
		goto Error;
	if (platform_notify)
		platform_notify(dev);
	error = device_create_file(dev, &uevent_attr);
	if (error)
		goto attrError;
	if (MAJOR(dev->devt)) {
		error = device_create_file(dev, &devt_attr);
		if (error)
			goto ueventattrError;
		error = device_create_sys_dev_entry(dev);	//创建"/sys/dev/char/xxx"或"/sys/dev/block/xxx"
		if (error)
			goto devtattrError;
		devtmpfs_create_node(dev);	//创建节点文件
	}
	error = device_add_class_symlinks(dev);		
        	if (error)
		goto SymlinkError;
	error = device_add_attrs(dev);
	if (error)
		goto AttrsError;
	error = bus_add_device(dev);	//将设备添加进总线
	if (error)
		goto BusError;
	error = dpm_sysfs_add(dev);
	if (error)
		goto DPMError;
	device_pm_add(dev);
	if (dev->bus)
		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,BUS_NOTIFY_ADD_DEVICE, dev);	//通知链发送通知

	kobject_uevent(&dev->kobj, KOBJ_ADD);
	bus_probe_device(dev);	//设备尝试匹配驱动并调用其probe方法
	if (parent)
		klist_add_tail(&dev->p->knode_parent,&parent->p->klist_children);

	if (dev->class) {
		mutex_lock(&dev->class->p->class_mutex);
		/* tie the class to the device */
		klist_add_tail(&dev->knode_class,&dev->class->p->class_devices);

		/* notify any interfaces that the device is here */
		list_for_each_entry(class_intf,&dev->class->p->class_interfaces, node)
			if (class_intf->add_dev)
				class_intf->add_dev(dev, class_intf);
		mutex_unlock(&dev->class->p->class_mutex);
	}
done:
	put_device(dev);
	return error;
 DPMError:
	bus_remove_device(dev);
 BusError:
	device_remove_attrs(dev);
 AttrsError:
	device_remove_class_symlinks(dev);
 SymlinkError:
	if (MAJOR(dev->devt))
		devtmpfs_delete_node(dev);
	if (MAJOR(dev->devt))
		device_remove_sys_dev_entry(dev);
 devtattrError:
	if (MAJOR(dev->devt))
		device_remove_file(dev, &devt_attr);
 ueventattrError:
	device_remove_file(dev, &uevent_attr);
 attrError:
	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
	kobject_del(&dev->kobj);
 Error:
	cleanup_device_parent(dev);
	if (parent)
		put_device(parent);
name_error:
	kfree(dev->p);
	dev->p = NULL;
	goto done;
}

     2.1.2.1 device_create_sys_dev_entry 创建设备入口

static int device_create_sys_dev_entry(struct device *dev)
{
	struct kobject *kobj = device_to_dev_kobj(dev);
	int error = 0;
	char devt_str[15];
	if (kobj) {
		format_dev_t(devt_str, dev->devt);	//devt_srt=主设备号:次设备号
		error = sysfs_create_link(kobj, &dev->kobj, devt_str);
	}
	return error;
}

创建"/sys/dev/char[block]/主设备号:次设备号"
     2.1.2.2 bus_add_device

int bus_add_device(struct device *dev)
{
	struct bus_type *bus = bus_get(dev->bus);
	int error = 0;

	if (bus) {
		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
		error = device_add_attrs(bus, dev);
		if (error)
			goto out_put;
		error = sysfs_create_link(&bus->p->devices_kset->kobj,&dev->kobj, dev_name(dev));
		if (error)
			goto out_id;
		error = sysfs_create_link(&dev->kobj,&dev->bus->p->subsys.kobj, "subsystem");
		if (error)
			goto out_subsys;
		klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);	//将设备添加至总线的设备链表
	}
	return 0;

out_subsys:
	sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
out_id:
	device_remove_attrs(bus, dev);
out_put:
	bus_put(dev->bus);
	return error;
}

    2,2 注销

void device_unregister(struct device *dev)
{
	pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
	device_del(dev);
	put_device(dev);
}

 

     3. 驱动注册与注销

     3.1 注册

int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	BUG_ON(!drv->bus->p);
	//判断驱动的方法与总线是否匹配
	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);		//总线添加设备驱动
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);
	if (ret)
		bus_remove_driver(drv);
	return ret;
}

     3.1.1 bus_add_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;

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

	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.kset = bus->p->drivers_kset;
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,"%s", drv->name);	//创建"/sys/bus/xxx/drivers"
	if (error)
		goto out_unregister;

	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);		//驱动匹配设备,并调用probe方法
		if (error)
			goto out_unregister;
	}
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);	//添加设备驱动到总线驱动链表
	module_add_driver(drv->owner, drv);
	error = driver_create_file(drv, &driver_attr_uevent);
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",__func__, drv->name);
	}
	error = driver_add_attrs(bus, drv);
	if (error) {
		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",__func__, drv->name);
	}

	if (!drv->suppress_bind_attrs) {
		error = add_bind_files(drv);
		if (error) {
			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",__func__, drv->name);
		}
	}
	kobject_uevent(&priv->kobj, KOBJ_ADD);
	return 0;
out_unregister:
	kobject_put(&priv->kobj);
	kfree(drv->p);
	drv->p = NULL;
out_put_bus:
	bus_put(bus);
	return error;
}

     3.1.1.1 driver_attach 设备驱动匹配

int driver_attach(struct device_driver *drv)
{
	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}

    3.1.1.1.1 __driver_attach

static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;
	if (!driver_match_device(drv, dev))	//设备与设备驱动的匹配
		return 0;
	if (dev->parent)	/* Needed for USB */
		device_lock(dev->parent);
	device_lock(dev);
	if (!dev->driver)	//存在设备驱动
		driver_probe_device(drv, dev);
	device_unlock(dev);
	if (dev->parent)
		device_unlock(dev->parent);
	return 0;
}

    3.1.1.1.1.1driver_match_device

static inline int driver_match_device(struct device_driver *drv,struct device *dev)
{
	return drv->bus->match ? drv->bus->match(dev, drv) : 1;	//若总线存在match方法调用总线的match方法
}

   3.1.1.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))
		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;
}

    3.1.1.1.1.2.1  really_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;
	if (driver_sysfs_add(dev)) {
		printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",__func__, dev_name(dev));
		goto probe_failed;
	}
	if (dev->bus->probe) {	//总线存在probe方法
		ret = dev->bus->probe(dev);	//则调用去probe方法
		if (ret)
			goto probe_failed;
	} else if (drv->probe) {	//驱动存在probe方法
		ret = drv->probe(dev);	//则调用设备驱动的probe方法 
		if (ret)
			goto probe_failed;
	}
	driver_bound(dev);	//捆绑设备文件,会调用总线的通知链回调函数
	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) {
		printk(KERN_WARNING"%s: probe of %s failed with error %d\n",drv->name, dev_name(dev), ret);
	}
	ret = 0;
done:
	atomic_dec(&probe_count);
	wake_up(&probe_waitqueue);
	return ret;
}

   3.2 注销

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

 

     4. 类的注册与注销

     4.1 注册

#define class_register(class)			\
({						\
	static struct lock_class_key __key;	\
	__class_register(class, &__key);	\
})
int __class_register(struct class *cls, struct lock_class_key *key)
{
	struct class_private *cp;
	int error;

	pr_debug("device class '%s': registering\n", cls->name);

	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
	if (!cp)
		return -ENOMEM;
	klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put);
	INIT_LIST_HEAD(&cp->class_interfaces);
	kset_init(&cp->class_dirs);
	__mutex_init(&cp->class_mutex, "struct class mutex", key);
	error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
	if (error) {
		kfree(cp);
		return error;
	}

	/* set the default /sys/dev directory for devices of this class */
	if (!cls->dev_kobj)
		cls->dev_kobj = sysfs_dev_char_kobj;		//sysfs_dev_char_kobj --> /sys/dev/char
#if defined(CONFIG_BLOCK)
	/* let the block class directory show up in the root of sysfs */
	if (!sysfs_deprecated || cls != &block_class)		//创建"/sys/block"
		cp->class_subsys.kobj.kset = class_kset;
#else
	cp->class_subsys.kobj.kset = class_kset;	//class_kset --> /sys/class
#endif
	cp->class_subsys.kobj.ktype = &class_ktype;
	cp->class = cls;
	cls->p = cp;

	error = kset_register(&cp->class_subsys);
	if (error) {
		kfree(cp);
		return error;
	}
	error = add_class_attrs(class_get(cls));
	class_put(cls);
	return error;
}

     4.2 注销

void class_unregister(struct class *cls)
{
	pr_debug("device class '%s': unregistering\n", cls->name);
	remove_class_attrs(cls);
	kset_unregister(&cls->p->class_subsys);
}

    4.3 驱动中注册与注销类的另一种方式

    4.3.1 注册类 class_create

#define class_create(owner, name)		\	//创建"/sys/(name)"
({					\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})
struct class *__class_create(struct module *owner, const char *name,struct lock_class_key *key)
{
	struct class *cls;
	int retval;

	cls = kzalloc(sizeof(*cls), GFP_KERNEL);
	if (!cls) {
		retval = -ENOMEM;
		goto error;
	}

	cls->name = name;
	cls->owner = owner;
	cls->class_release = class_create_release;

	retval = __class_register(cls, key);		//实质上也是调用了__class_register函数
	if (retval)
		goto error;

	return cls;

error:
	kfree(cls);
	return ERR_PTR(retval);
}

    4.3.2 注销类 class_destroy

void class_destroy(struct class *cls)
{
	if ((cls == NULL) || (IS_ERR(cls)))
		return;

	class_unregister(cls);
}

四. 总线设备驱动类框架的搭建(eg:platform)
     1.定义总线类型结构体

struct bus_type platform_bus_type = {  
    .name       = "platform",       //总线名   
    .dev_attrs  = platform_dev_attrs,   //设备属性   
    .match      = platform_match,       //匹配函数   
    .uevent     = platform_uevent,      //事件函数   
    .pm     = &platform_dev_pm_ops, //电源管理函数集   
}; 

      2.定义总线作为设备的设备结构体--总线本身也是一个设备

struct device platform_bus = {
	.init_name	= "platform",
};

     3.注册作为设备的总线设备

platform_bus_init()-->device_register(&platform_bus)
     4.注册总线

platform_bus_init()-->bus_register(&platform_bus_type)

     5.这里可以是设备注册或者设备驱动注册(以设备注册先为例)

     5.1 定义总线下的设备结构体

static struct platform_device platform_device_1 = {  
    .name   = "paltform_1",  
    .id = -1,               //设备id一般都设置为-1   
}; 

      5.1.1 注册设备

platform_device_register(&platform_device_1); //-->platform_device_add-->device_add(&pdev->dev) 

      6.定义设备驱动

static struct platform_driver platform_1_driver = {
	.driver = {
		.name = "platform_1",
		.owner = THIS_MODULE,
	},
	.probe = platform_1_probe,
	.remove = platform_1_remove,
};

     7.注册设备驱动

platform_driver_register(&platform_1_driver);	//-->driver_register(&drv->driver)

    8. 至于类的添加

class_create(THIS_MODULES,"platfrom_1");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值