linux内核之class介绍(一)

class的概念
class是设备的更高层视图,抽象出了底层的实现细节.驱动程序会区分SCSI硬盘和ATA硬盘,但在class层他们都是
硬盘.classes帮助用户空间只需要知道这些是什么设备,而不需要关心他们是怎么连接和工作的.(A class is a higher-level view of a device that abstracts out low-level implementation details. Drivers may see a SCSI disk or an ATA disk, but,at the class level, they are all simply disks. Classes allow user space to work with devices based on what they do, rather than how they are connected or how they work.)

class结构体
include\linux\Device.h

struct class {
	const char		*name;
	struct module		*owner;

	struct class_attribute		*class_attrs;
	struct device_attribute		*dev_attrs;
	struct bin_attribute		*dev_bin_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 subsys_private *p;
};

@name: Name of the class.

	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);

该名字用于设置subsys_private.subsys.kobj的名字,也就是子系统的目录名,如:sys/class/name

@owner: The module owner.
表示该class所属的module

@class_attrs: Default attributes of this class.
表示class默认的属性,在class注册时创建

	error = add_class_attrs(class_get(cls));

@dev_attrs: Default attributes of the devices belong to the class.
@dev_bin_attrs: Default binary attributes of the devices belong to the class.
以上dev_attrs,dev_bin_attrs是设备相关的属性,在设备添加到该class时在设备目录需要创建的属性文件

static int device_add_attrs(struct device *dev)
{
	struct class *class = dev->class;
	const struct device_type *type = dev->type;
	int error;

	if (class) { // 如果定义了class,添加class的设备属性文件dev_attrs,dev_bin_attrs
		error = device_add_attributes(dev, class->dev_attrs);
		if (error)
			return error;
		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
		if (error)
			goto err_remove_class_attrs;
	}
	.............
}

@dev_kobj: The kobject that represents this class and links it into the hierarchy.
dev_kobj是kobject指针,指向sysfs_dev_char_kobj(sys/dev/char),表示属于该class的设备在sys/dev/char目录

	/* set the default /sys/dev directory for devices of this class */
	if (!cls->dev_kobj)
		cls->dev_kobj = sysfs_dev_char_kobj;// sys/dev/char

sysfs_dev_char_kobj在这里创建,代表/sys/dev/char目录:

int __init devices_init(void)
{
	// 创建/sys/devices目录
	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
	if (!devices_kset)
		return -ENOMEM;
	// 创建/sys/dev目录
	dev_kobj = kobject_create_and_add("dev", NULL);
	if (!dev_kobj)
		goto dev_kobj_err;
	// 创建/sys/dev/block目录
	sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
	if (!sysfs_dev_block_kobj)
		goto block_kobj_err;
	// 创建/sys/dev/char目录
	sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
	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;
}

@dev_uevent: Called when a device is added, removed from this class, or a
few other things that generate uevents to add the environment
variables.
device加入class或从class移除,或者一些其它事件发生时调用uevent来添加环境变量
driver/base/core.c

static int dev_uevent(struct kset *kset, struct kobject *kobj,
		      struct kobj_uevent_env *env)
{
	struct device *dev = to_dev(kobj);
	int retval = 0;

	/* add device node properties if present */
	if (MAJOR(dev->devt)) {
		const char *tmp;
		const char *name;
		mode_t mode = 0;

		add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
		add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
		name = device_get_devnode(dev, &mode, &tmp);
		if (name) {
			add_uevent_var(env, "DEVNAME=%s", name);
			kfree(tmp);
			if (mode)
				add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
		}
	}

	if (dev->type && dev->type->name)
		add_uevent_var(env, "DEVTYPE=%s", dev->type->name);

	if (dev->driver)
		add_uevent_var(env, "DRIVER=%s", dev->driver->name);

	/* have the bus specific function add its stuff */
	if (dev->bus && dev->bus->uevent) {
		retval = dev->bus->uevent(dev, env);
		if (retval)
			pr_debug("device: '%s': %s: bus uevent() returned %d\n",
				 dev_name(dev), __func__, retval);
	}

	/* have the class specific function add its stuff */
	if (dev->class && dev->class->dev_uevent) { // 调用所属class->dev_uevent
		retval = dev->class->dev_uevent(dev, env);
		if (retval)
			pr_debug("device: '%s': %s: class uevent() "
				 "returned %d\n", dev_name(dev),
				 __func__, retval);
	}

	/* have the device type specific function add its stuff */
	if (dev->type && dev->type->uevent) {
		retval = dev->type->uevent(dev, env);
		if (retval)
			pr_debug("device: '%s': %s: dev_type uevent() "
				 "returned %d\n", dev_name(dev),
				 __func__, retval);
	}

	return retval;
}

static const struct kset_uevent_ops device_uevent_ops = {
	.filter =	dev_uevent_filter,
	.name =		dev_uevent_name,
	.uevent =	dev_uevent,
};

int __init devices_init(void)
{
	// 创建/sys/devices目录
	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
	if (!devices_kset)
		return -ENOMEM;
	.......
}

@devnode: Callback to provide the devtmpfs.
用于返回device设备节点的相对路径

@class_release: Called to release this class.
用于释放class

@dev_release: Called to release the device.
用于释放device

@suspend: Used to put the device to sleep mode, usually to a low power
state.
用于让设备进入睡眠模式,通常是低功耗模式

@resume: Used to bring the device from the sleep mode.
让设备退出睡眠模式

@ns_type: Callbacks so sysfs can detemine namespaces.
sysfs用于确定命名空间(namespaces)

@namespace: Namespace of the device belongs to this class.

@pm: The default device power management operations of this class.
电源管理用的函数集合

@p: The private data of the driver core, no one other than the
driver core can touch this.
p指向subsys_private结构体,用于保存归属该class的device和driver链表:

struct subsys_private {
	struct kset subsys; // the struct kset that defines this subsystem
	struct kset *devices_kset; // the list of devices associated

	struct kset *drivers_kset; // the list of drivers associated
	struct klist klist_devices;// the klist to iterate over the @devices_kset
	struct klist klist_drivers;// the klist to iterate over the @drivers_kset
	struct blocking_notifier_head bus_notifier;//the bus notifier list for anything that cares about things on this bus.
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;//pointer back to the struct bus_type that this structure is associated with.

	struct list_head class_interfaces;// list of class_interfaces associated
	struct kset glue_dirs;//"glue" directory to put in-between the parent device to  avoid namespace conflicts
	struct mutex class_mutex;//mutex to protect the children, devices, and interfaces lists.
	struct class *class; // pointer back to the struct class that this structure is associated with.
};

猜你喜欢

转载自blog.csdn.net/qq_36412526/article/details/84313114