编程接口
int device_register(struct device * dev);
总线需要初始化以下四个参数
- parent
- name
- bus_id
- bus
当一个设备的引用数(reference )为0时,将会被内核移除。我们可以使用下面的API调整(reference )。
struct device * get_device(struct device * dev);
void put_device(struct device * dev);
访问内核的锁API
void lock_device(struct device * dev);
void unlock_device(struct device * dev);
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);
};
设备的属性可以通过sysfs文件系统展示(export)出来。关于sysfs的更多信息可以查看Documentation/filesystems/sysfs.txt 文档。
如Documentation/kobject.txt中所述,必须在生成KOBJ_ADD uevent之前创建设备属性。实现这一点的唯一方法是定义一个属性组。可以使用DEVICE_ATTR宏定义来声明这样的一个属性组。
#define DEVICE_ATTR(name,mode,show,store)
/*----------例程------------*/
static DEVICE_ATTR(type, 0444, show_type, NULL);
static DEVICE_ATTR(power, 0644, show_power, store_power);
这声明了两个struct device_属性类型的结构,其各自的名称为“dev_attr_type”和“dev_attr_power”。这两个属性可以按如下方式组织为一个组:
/*-------属性数组-------*/
static struct attribute *dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_power.attr,
NULL,
};
/*-------将对应的属性数组赋值给 attribute_group.attrs---*/
static struct attribute_group dev_attr_group = {
.attrs = dev_attrs,
};
/*-----将属性组组成对应的属性组数组---*/
static const struct attribute_group *dev_attr_groups[] = {
&dev_attr_group,
NULL,
};
/*----将属性绑定到设备上----*/
struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
dev->groups = netiucv_attr_groups;
/*----最后注册--------*/
ret = device_register(dev);
关于device_register
上面我们讲到会使用device_register 函数来注册设备,将设备属性绑定起来。
drivers/base/core.c:1125:int device_register(struct device *dev)
device_initialize(dev);
return device_add(dev);
void device_initialize(struct device *dev)
...
int device_add(struct device *dev)
# 在这里创建对应的 sysfs下的设备属性文件
error = device_create_file(dev, &dev_attr_uevent);
int device_create_file(struct device *dev,
const struct device_attribute *attr)
sysfs_create_file(&dev->kobj, &attr->attr);