创建sysfs节点之device_create_file、sysfs_create_group

sysfs属性节点可以实现用户空间与硬件交互,如设置管教电平,设置寄存器值等,控制驱动的具体功能。下面是如何在驱动中创建设备属性节点:

一、device_create_file

device_create_file用于在sys下创建设备的属性节点

int device_create_file(struct device *dev,  const struct device_attribute *attr)

注意:第一个参数为device型,不是cdev,这个参数一般使用device_create()的返回值
device_attribute : 使用DEVICE_ATTR(_name, _mode, _show, _store)初始化,注意name的形式

现在就是要创建这个函数需要的两个参数。

1. 初始化属性结构体device_attribute

1).相关结构体

struct attribute {
    const char        *name;           //  属性文件的名字 
    struct module        *owner;       //  属性文件的所有者
    mode_t            mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lock_class_key    *key;
    struct lock_class_key    skey;
#endif
};
struct device_attribute {
    struct attribute    attr;                              //  内置的attribute 结构体
    ssize_t (*show)(struct device *dev, struct device_attribute *attr,   //属性文件的show方法(也就是读)
            char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr,  //属性文件的store方法(也就是写)
             const char *buf, size_t count);
};

2). 初始化device_attribute结构体

  • 使用DEVICE_ATTR初始化device_attribute
DEVICE_ATTR(_name, _mode, _show, _store)

_name:名称,也就是将在sysfs中生成的文件名称。
_mode:上述文件的访问权限,与普通文件相同,UGO的格式。只读0444,只写0222,或者读写都行的0666。
_show:显示函数,cat该文件时,此函数被调用。
_store:写函数,echo内容到该文件时,此函数被调用

宏定义:

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

#define __ATTR(_name,_mode,_show,_store) { \
   .attr = {.name = __stringify(_name), .mode = _mode }, \
   .show = _show,
   .store = _store,}

可以发现DEVICE_ATTR就是初始化了结构体device_attribute,下面是实例:

static DEVICE_ATTR(demo, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
static DEVICE_ATTR(demo, 0444,demo_show,NULL);

**注意:**mode可以直接定义成只读0444,只写0222,或者读写都行的0666。。
_show和_store函数当没有的时候用NULL赋值,对函数的名称和内容没有具体要求,甚至可以和别的属性相同。

  • 直接赋值device_attribute结构体
    直接赋值device_attribute结构体代码示例:
static struct device_attribute dev_attr_demo = {
    .attr = {
        .name = "demo", 
        .mode = (S_IRUGO | S_IWUSR) 
    },
    .show = demo_show,
    .store = demo_store,
};

2. 构建 struct device *dev 参数

1). 没有总线的字符设备驱动

struct class *class_create(struct module *owner, const char *name)

参数:
owner : 一般为 THIS_MODULE
name : 创建的class类名
对应是在/sys/class/下创建类目录

struct class_device *device_create(struct class        *cls,
                                         struct class_device *parent,
                                         dev_t               devt,
                                         void       *drvdata,
                                         const char          *fmt, ...)

struct class: class_create()返回值,必须在本函数调用之前先被创建
parent:父节点指针
devt:设备号,如果devt不为0,创建设备文件
drvdata:被添加到该设备回调的数据
fmt:设备名称

对应是在/dev/下创建设备节点
例子:device_create(demo_class, NULL, MKDEV(tmp_major, 0), NULL, "demo");

注意:在删除模块的时候要使用以下两个函数删除创建的文件

device_destroy(struct class *cls, dev_t devt);
class_destroy(struct class *cls);

注意两个函数的调用顺序

2). platform总线驱动

直接在probe函数中调用device_create_file创建属性节点。
代码示例:

static DEVICE_ATTR(led, S_IWUSR | S_IRUGO, NULL, led_action_store);
static int __devinit demo_probe(struct platform_device *pdev)
{
    int ret = 0;

    /* led gpio init. */
        ..................
    ret = device_create_file(&pdev->dev, &dev_attr_demo);
    if (ret)
        return ret;

    return 0;
}

3.代码示例(没有总线的字符设备驱动)

.......................
static ssize_t demo_show(struct device *dev, struct device_attribute *attr, char *buf)
{
    sprintf(buf,"read,demo temp is %d\n",temp);  /*将“read,demo temp is %d”写入buf中,%d是temp的值*/
    return 0;
}

static ssize_t demo_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size)
{
    sscanf(buf, "%d", &temp);  /*将buf中的值以%d的形式赋值给temp*/

    printk(KERN_NOTICE "write,demo temp is %d/n",temp);
    return size;
}

/*这里show和store的函数名没有格式要求,可以为NULL,但是函数的参数必须符合格式要求*/
static DEVICE_ATTR(demo, (S_IRUGO | S_IWUSR),demo_show,demo_store);
.................
int demo_init(void) 
{
    .................
    demo_class = class_create(THIS_MODULE, "demo");  
    devdemo = device_create(demo_class, NULL, MKDEV(demo_major, 0), NULL, "cdevdemo");  
    device_create_file(demo,&dev_attr_demo);
    .....................
}

二、sysfs_create_group

sysfs_create_group可以用于一次创建多个属性节点

1. 初始化device_attribute,这里创建多个节点

static DEVICE_ATTR(demo1, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);

2. 定义属性结构体数组

static struct attribute *demo_attrs[] = {  
       &dev_attr_demo1.attr,
       &dev_attr_demo2.attr,
       &dev_attr_demo3.attr,
       NULL,      //这里必须要以NULL结尾  
};  //末尾有分号

3. 定义attribute属性结构体数组到属性组中

static const struct attribute_group demo_attr_grp = {  
       .attrs = demo_attrs,  
}  

4. 创建sysfs接口

sysfs_create_group(&pdev->dev.kobj,&dev_attr_led);

5. 代码示例:

static DEVICE_ATTR(demo1, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
static DEVICE_ATTR(demo2, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);
static DEVICE_ATTR(demo3, (S_IRUGO | S_IWUSR | S_IWGRP),demo_show,demo_store);

static struct attribute *demo_attrs[] = {  
       &dev_attr_demo1.attr,
       &dev_attr_demo2.attr,
       &dev_attr_demo3.attr,
       NULL,      //这里必须要以NULL结尾  
};  //末尾有分号

static const struct attribute_group demo_attr_grp = {  
       .attrs = demo_attrs,  
}  

 static int __devinit demo_probe(struct platform_device *pdev)
{
    int ret = 0;

    /* led gpio init. */
        ..................
    ret = sysfs_create_group(&pdev->dev.kobj,&demo_attr_grp);
    if (ret)
        return ret;

    return 0;
}

6. 删除接口:

sysfs_remove_groupsysfs_create_group(&pdev->dev.kobj,&demo_attr_grp);
  • 7
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
`device_create_file` 和 `sysfs_create_file` 函数都可以用于在 sysfs 文件系统中创建文件,但它们的使用场景略有不同。 `sysfs_create_file` 函数是一个通用的函数,它可以在 sysfs 文件系统的任意位置创建文件。该函数的原型如下: ```c int sysfs_create_file(struct kobject *kobj, const struct attribute *attr); ``` 其中,`kobj` 参数是指向 `struct kobject` 结构体的指针,该结构体表示要在其下面创建文件的 sysfs 对象。`attr` 参数是指向 `struct attribute` 结构体的指针,该结构体描述了要创建的文件的属性。`sysfs_create_file` 函数会在 sysfs 文件系统中创建一个与 `attr` 中描述的属性相关联的文件,并将其与 `kobj` 参数指向的 sysfs 对象关联起来。 相比之下,`device_create_file` 函数更加专业化。它是针对 Linux 设备驱动程序的一种特殊机制,用于在与设备相关联的 sysfs 对象下创建文件。该函数的原型如下: ```c int device_create_file(struct device *dev, const struct attribute *attr); ``` 其中,`dev` 参数是指向 `struct device` 结构体的指针,该结构体表示与设备相关联的设备对象。`attr` 参数是指向 `struct attribute` 结构体的指针,该结构体描述了要创建的文件的属性。`device_create_file` 函数会在 sysfs 文件系统中创建一个与 `attr` 中描述的属性相关联的文件,并将其与 `dev` 参数指向的设备对象关联起来。 因此,如果你需要在 sysfs 文件系统的任意位置创建文件,可以使用 `sysfs_create_file` 函数。而如果你需要在 Linux 设备驱动程序中为设备创建文件,应该使用 `device_create_file` 函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值