在内核驱动中添加sysfs接口

linux内核中提供了sysfs接口给用户使用,用户可以通过echo cat等命令来查看驱动中某些变量的值。

//灯灭
echo 0 >/sys/class/leds/firefly:blue:power/brightness 
//灯亮
echo 1 >/sys/class/leds/firefly:blue:power/brightness 

接口创建

声明节点,创建读写函数

使用DEVICE_ATTR可以声明一个sysfs节点,原型为DEVICE_ATTR(_name, _mode, _show, _store),其定义位于include/linux/device.h中,定义如下所示:

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

其中_mode定义如下:

400 拥有者能够读,其他任何人不能进行任何操作;
644 拥有者都能够读,但只有拥有者可以编辑;
660 拥有者和组用户都可读和写,其他人不能进行任何操作;
664 所有人都可读,但只有拥有者和组用户可编辑;
700 拥有者能够读、写和执行,其他用户不能任何操作;
744 所有人都能读,但只有拥有者才能编辑和执行;
755 所有人都能读和执行,但只有拥有者才能编辑;
777 所有人都能读、写和执行(该设置通常不是好想法)
使用方法为:

static ssize_t show_my_device(struct device *dev,
              struct device_attribute *attr, char *buf)   //cat命令时,将会调用该函数
{
	return buf;
}

static ssize_t set_my_device(struct device *dev,
             struct device_attribute *attr,
             const char *buf, size_t len)   //echo命令时,将会调用该函数.
{
	return len;
}
static DEVICE_ATTR(xx_dev, S_IWUSR|S_IRUSR, show_my_device, set_my_device);   //定义一个名字为my_device_test的设备属性文件

其中,函数show_my_device和set_my_device即是cat和echo命令对应的执行函数。

定义struct attribute和struct attribute_group数组

static struct attribute *xx_attributes[]={
 
  /*上述使用了DEVICE_ATTR声明节点名字为xx_dev,
  * 则struct attribute名字应为:
  *  dev_attr_ + (节点名) + .attr
  * 所以名字为dev_attr_xx_dev.attr
  */
  &dev_attr_xx_dev.attr,
 NULL,
};


static const struct attribute_group xx_attrs={
 .attrs = xx_attributes,//引用上述struct attribute数组
};

注册接口

在驱动函数中调用sysfs_create_group()和sysfs_remove_group()即可注册或删除节点

int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp)
int sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp)

驱动程序示例

static unsigned int xxx = 0;

static ssize_t show_my_device(struct device *dev, struct device_attribute *attr, char *buf)
{
    //打印相关信息
    return sprintf(buf, "%s:%d.\n", "xxx", xxx);
}

static ssize_t set_my_device(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    //从用户态读取相关信息
    sscanf(buf, "%d", &xxx);
    return count;
}

static DEVICE_ATTR(xxx_dev, 0600, show_my_device, set_my_device);
static struct attribute *xxx_attributes[]={
    &dev_attr_xxx_status.attr,
    NULL,
};

static const struct attribute_group xxx_attrs={
    .attrs = xxx_attributes,
};

static int xxx_probe(struct platform_device *pdev)
{
    sysfs_create_group(&pdev->dev.kobj, &xxx_attrs);
    return 0;
}

static int xxx_remove(struct platform_device *pdev)
{
    sysfs_remove_group(&pdev->dev.kobj, &xxx_attrs);
    return 0;
}

static const struct of_device_id xxx_of_match[] = {
    {.compatible = "xx,xxx"},
};

static struct platform_driver xxx_driver = {
    .probe = xxx_probe,
    .remove = xxx_remove,
    .driver = {
    .name = "xxx",
    .owner = THIS_MODULE,
    .of_match_table = xxx_of_match,
	 },
};

static int __init xxx_init(void)
{
    return platform_driver_register(&xxx_driver );
}

static void __exit xxx_exit(void)
{
    platform_driver_unregister(&xxx_driver);
}

module_init(xxx_init);
module_exit(xxx_exit);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值