类的简单使用

类在Linux内核中提供设备的高层抽象,隐藏底层实现细节。类通常位于/sys/class目录下,如网络接口在/sys/class/net。关键接口包括class_create、class_destroy、class_register、class_unregister。设备的创建与注册涉及device_create、device_register等,同时需要实现show和store函数。DEVICE_ATTR宏用于定义设备属性,并影响sysfs中的显示和交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类是一个设备的高层视图,它抽象出了底层的实现细节。类允许用户空间使用设备所提供的功能,而不关心设备时如何连接的,以及它们时怎么工作的。

几乎所有的类都显示在/sys/class目录中。举个例子,网络接口都集中在/sys/class/net下。

 

结构体:

/**
 * struct class - device classes
 * @name:	Name of the class.
 * @owner:	The module owner.
 * @class_attrs: Default attributes of this class.
 * @dev_groups:	Default attributes of the devices that belong to the class.
 * @dev_kobj:	The kobject that represents this class and links it into the hierarchy.
 * @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.
 * @devnode:	Callback to provide the devtmpfs.
 * @class_release: Called to release this class.
 * @dev_release: Called to release the 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.
 * @shutdown:	Called at shut-down time to quiesce the device.
 * @ns_type:	Callbacks so sysfs can detemine 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.
 *
 * 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.
 */
struct class {
	const char		*name;
	struct module		*owner;

	struct class_attribute		*class_attrs;
	const struct attribute_group	**dev_groups;
	struct kobject			*dev_kobj;

	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
	char *(*devnode)(struct device *dev, umode_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);
	int (*shutdown)(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;
};

 

主要接口:

class_create和class_destroy

//创建
/* This is a #define to keep the compiler from merging different
 * instances of the __key variable */
#define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})


/**
 * class_create - create a struct class structure
 * @owner: pointer to the module that is to "own" this struct class
 * @name: pointer to a string for the name of this class.
 * @key: the lock_class_key for this class; used by mutex lock debugging
 *
 * This is used to create a struct class pointer that can then be used
 * in calls to device_create().
 *
 * Returns &struct class pointer on success, or ERR_PTR() on error.
 *
 * Note, the pointer created here is to be destroyed when finished by
 * making a call to class_destroy().
 */
struct class *__class_create(struct module *owner, const char *name,
			     struct lock_class_key *key)
{
//...
}


//销毁
/**
 * class_destroy - destroys a struct class structure
 * @cls: pointer to the struct class that is to be destroyed
 *
 * Note, the pointer to be destroyed must have been created with a call
 * to class_create().
 */
void class_destroy(struct class *cls)
{
	if ((cls == NULL) || (IS_ERR(cls)))
		return;

	class_unregister(cls);
}

还有一组用法是:

class_register和class_unregister

/* This is a #define to keep the compiler from merging different
 * instances of the __key variable */
#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) {
//...
}

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

这两对接口完成的工作几乎是一致的,class_register和class_unregister需要自己申请class结构的内存。

 

调用完class_create后,会在/sys/class下创建对应的文件夹。

static struct class* longlong_class = NULL;

longlong_class = class_create(THIS_MODULE, "longlong");

if(IS_ERR(longlong_class)){
		err = PTR_ERR(longlong_class);
		printk(KERN_ALERT "Failed to create longlong class.\n");
		goto destroy_cdev;
}

//...



destroy_class:
	class_destroy(longlong_class);

以上代码会创建一个名为longlong的文件夹。

 

后面可以通过device_create()、device_register()、deivce_add()创建设备,当然设备节点也有其对应销毁方法device_destroy。

struct device* mdevice= NULL;
mdevice= device_create(longlong_class, NULL, dev, "%s", "longlong");
if(IS_ERR(temp)){
		err = PTR_ERR(temp);
		printk(KERN_ALERT "Failed to create longlong device.\n");
		goto destroy_class;
}

//...
destroy_device:
	device_destroy(longlong_class, dev);

以上代码会在/dev/和sys/class/longlong下创建文件longlong

 

而后可以使用device_create_file创建设备文件

/**
 * device_create_file - create sysfs attribute file for device.
 * @dev: device.
 * @attr: device attribute descriptor.
 */
int device_create_file(struct device *dev,
		       const struct device_attribute *attr)


/* interface for exporting device attributes */
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);
};

/*
 * show: 显示函数,cat该文件时,此函数被调用。
 * store:写函数,echo内容到该文件时,此函数被调用。
 */
err = device_create_file(mdevice, &dev_attr_val);
	if(err < 0){
		printk(KERN_ALERT "Failed to create attribute val.\n");
		goto destroy_device;
}

当然到这里之后device_attribute里面show和store还是要我们自己实现的。

这里需要提到一个宏DEVICE_ATTR

#define DEVICE_ATTR(_name,_mode,_show,_store)

其中最后两个参数就是show和store函数。

// * define the device properties
static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, longlong_val_show, longlong_val_store);

除了show和store之外,这里的第一个参数_name也很好玩,在上面提到的device_create_file中的第二个参数,需要传入dev_attr_[_name]。这个_name也是最后在sys/class/longlong/longlong/下显示的名字,可以对它进行cat和echo。

如果非要问为什么会这样的话,那就要看看DEVICE_ATTR宏的内容了。

#define DEVICE_ATTR(_name,_mode,_show,_store) \
  struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)

这个宏用名字拼接的方法创建了device_attribute结构。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值