基本设备结构¶
请参阅针对 struct device
的 kerneldoc。
编程接口¶
发现设备的总线驱动程序使用此方法向核心注册设备
int device_register(struct device * dev);
总线应初始化以下字段
parent
name
bus_id
bus
当设备的引用计数变为 0 时,会从核心中移除设备。 可以使用以下方法调整引用计数
struct device * get_device(struct device * dev);
void put_device(struct device * dev);
get_device()
将返回指向传递给它的 struct device
的指针(如果引用尚未为 0)(如果它已经在被移除的过程中)。
驱动程序可以使用以下方法访问设备结构中的锁
void lock_device(struct device * dev);
void unlock_device(struct device * dev);
属性¶
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);
};
设备驱动程序可以通过 sysfs 导出设备的属性。
有关 sysfs 如何工作的更多信息,请参见 sysfs - 用于导出内核对象的_文件系统。
正如在 您从未想了解的关于 kobject、kset 和 ktype 的一切 中所解释的那样,设备属性必须在生成 KOBJ_ADD uevent 之前创建。 实现这一点的唯一方法是定义一个属性组。
属性使用名为 DEVICE_ATTR 的宏声明
#define DEVICE_ATTR(name,mode,show,store)
示例:
static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(power, 0644, power_show, power_store);
辅助宏可用于模式的常用值,因此上述示例可以简化为:
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RW(power);
这声明了两个类型为 struct device_attribute
的结构,分别名为 'dev_attr_type' 和 'dev_attr_power'。 这两个属性可以按如下方式组织成一个组
static struct attribute *dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_power.attr,
NULL,
};
static struct attribute_group dev_group = {
.attrs = dev_attrs,
};
static const struct attribute_group *dev_groups[] = {
&dev_group,
NULL,
};
辅助宏可用于单个组的常见情况,因此可以使用以下方法声明以上两个结构:
ATTRIBUTE_GROUPS(dev);
然后可以通过在调用 struct device
中的组指针之前设置 device_register()
来将此组数组与设备关联
dev->groups = dev_groups;
device_register(dev);
device_register()
函数将使用“groups”指针创建设备属性,并且 device_unregister()
函数将使用此指针删除设备属性。
警告:尽管内核允许随时在设备上调用 device_create_file()
和 device_remove_file()
,但用户空间对何时创建属性有严格的期望。 当新设备在内核中注册时,会生成一个 uevent 以通知用户空间(如 udev)有新设备可用。 如果在设备注册后添加属性,则用户空间将不会收到通知,并且用户空间将不会知道新属性。
这对于需要在驱动程序探测时发布设备的其他属性的设备驱动程序来说非常重要。 如果设备驱动程序只是在传递给它的设备结构上调用 device_create_file()
,那么用户空间将永远不会收到新属性的通知。