1.设备类属性
在Linux上,设备类属性(sysfs)是一种用于访问和修改设备属性的机制,sysfs提供了 一个虚拟文件系统,它代表了内核中的设备树,通过这个文件系统,可以查看和修改设备 及其属性状态,在硬件调试阶段非常实用。 再简化理解: class_attribute是一种用于向用户空间暴露设备类(class)属性的机制, 它允许内核驱动将设备类的特定信息,导出到/sys/class/目录下,供用户空间程序读取或修改。
2.class_attribute使用API接口
class_attribute结构体构成:
struct class_attribute {
struct attribute attr;
ssize_t (*show)(struct class *class, struct class_attribute *attr, char *buf);//cat 读取值
ssize_t (*store)(struct class *class, struct class_attribute *attr, const char *buf, size_t count);//echo 修改值
};
show---读取时回调 store--修改存储时回调 常见使用方法:
// 注册类属性
int class_create_file(struct class *class, const struct class_attribute *attr);
// 注销类属性
void class_remove_file(struct class *class, const struct class_attribute *attr);
3.实际平台使用案例
我们在平台上实现一个设备类属性操作,
3.1 class_attribute属性定义
//定义设备类属性
static struct class_attribute my_char_device_class_attrs[] = {
__ATTR(device_attr_name, 0644, my_char_device_attr_show, my_char_device_attr_store),
__ATTR_NULL, //必须以NULL 结尾
//上面权限控制
//0444 只读属性
//0644 可读可写属性
};
//3. 创建设备节点 (可以不用,一般加上)
//3.1 创建节点对象
class_p = class_create(THIS_MODULE, "mychar");//生成sys/class/mychar
if(IS_ERR(class_p))
{
ret = -ENOMEM;
goto err3;
}
//注册类属性,这个设备类属性,用于供用户层调用
//这个类属性,常用于设备控制(如调整采样频\暴露设备状态[温度\功耗等])
//高级用法:批量注册类属性,class_add_attrs(class, class_attrs)
ret = class_create_file(class_p, &my_char_device_class_attrs[0] );
if(ret)
{
dev_err(device_p, "Failed to create attribute\r\n");
return ret;
}
//设置类数据,以便在回调函数中访问
// class_set_devdata(device_p,data);//通过class_get_devdata 获取!!
for(i = 0; i < count; ++i)
{
char drv_name[20] = {0};
sprintf(drv_name, "mychar%d", i);
//3.2 创建设备节点 (导出设备信息到用户空间)
device_p = device_create(class_p, NULL, MKDEV(MAJOR(dev_num),i), NULL, drv_name);
if (IS_ERR(device_p))
{
ret = -ENOMEM;
goto err4;
}
}
3.2 设备类属性读写
实际就是定义读写函数
static unsigned long my_char_device_attr_value = 0;
//定义类属性的show函数(读取属性值)
static ssize_t my_char_device_attr_show(struct class *class,
struct class_attribute *attr,
char *buf)
{
//通过 cat /sys/class/class_attr_name
//可以通过class,获取到deive data
// class_get_devdata(class);
return sprintf(buf,"device_attr: %u\n", my_char_device_attr_value);
}
//定义类属性的store函数(修改属性值)
static ssize_t my_char_device_attr_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t count)
{
//对于store函数中,验证用户输入,防止非法值导致系统异常
//对于并发访问,若属性涉及共享资源,需要添加适当的锁机制(如:mutex)
//通过 echo xxx > /sys/class/class_attr_name
int ret ;
ret = kstrtoul(buf,10, &my_char_device_attr_value); //10表示 十进制
if(ret)
return ret;//失败
return ret;
}
4. 结果分析
[root@dong:~]cd /sys/class
[root@dong:/sys/class]ls
backlight i2c-adapter mtd scsi_changer tty
bdi i2c-dev mychar scsi_device udc
block ieee80211 net scsi_disk vc
bsg input phy scsi_generic vtconsole
dma leds power_supply scsi_host wakeup
drm mdio_bus pps sound
extcon mem ptp spi_master
gpio misc pwm spidev
graphics mmc_host regulator thermal
[root@dong:/sys/class]cd mychar
[root@dong:/sys/class/mychar]ls
device_attr_name mychar1 mychar3
mychar0 mychar2
[root@dong:/sys/class/mychar]cat device_attr_name
device_attr: 0
[root@dong:/sys/class/mychar]echo 1 > device_attr_name
^C
[root@dong:/sys/class/mychar]cat device_attr_name
device_attr: 1
[root@dong:/sys/class/mychar]
5.总结
上述操作过程中,如果考虑多线程安全,需要对操作资源进行保护!!
您还没有登录,请您登录后发表评论。