如何在平台驱动程序中将文件操作附加到sysfs属性? [英] How to attach file operations to sysfs attribute in platform driver?

查看:136
本文介绍了如何在平台驱动程序中将文件操作附加到sysfs属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为我们开发的外围设备编写了平台驱动程序,并希望向sysfs公开一些配置选项.我已经设法在Probe函数中使用属性struct(请参见下文)和sysfs_create_file创建适当的文件,但是我不知道如何将show/store函数附加到平台驱动程序中的结构上.

I wrote a platform driver for a peripheral we developed and would like to expose some configuration options to the sysfs. I have managed to create the appropriate files using attribute structs (see below) and sysfs_create_file in the probe function, but I can't figure out how to attach the show/store functions to the structs in a platform driver.

我在网上找到的大多数资源都使用device_attribute结构或类似的方法来创建文件,这在这里也合适吗?平台驱动程序还有另一种方法吗?

Most resources I found online used a device_attribute struct or something similar to create their files, is that also appropriate here? Is there another way to do this for a platform driver?

我的属性结构如下:

struct attribute subkey_attr = {
    .name = "subkeys",
    .mode = S_IWUGO | S_IRUGO,
};

然后使用此调用注册文件:

And I register the file using this call:

riddler_kobject = &pdev->dev.kobj;
ret_val = sysfs_create_file(riddler_kobject, &subkey_attr);

推荐答案

它可以归结为下一个:

  • struct device(来自您的struct platform_device)中的现有kobject重复使用为sysfs_create_group()(而不是创建自己的kobject)
  • 使用DEVICE_ATTR()声明struct device_attribute,而不是常规的__ATTR(),它会创建struct kobj_attribute.
  • reuse existing kobject from struct device (from your struct platform_device) for sysfs_create_group() (instead of creating your own kobject)
  • use DEVICE_ATTR() to declare struct device_attribute instead of regular __ATTR(), which creates struct kobj_attribute.

这是我为平台驱动程序创建sysfs属性的方法.

Here is how I created sysfs attributes for my platform driver.

  1. 为您的sysfs属性(文件)创建要在show()/store()操作中用作私有数据的结构.例如:

  1. Create structure you'll be using as private data in show() / store() operations for your sysfs attribute (file). For example:

struct mydrv {
    struct device *dev;
    long myparam;
};

  • 在驱动程序的probe()中分配此结构:

  • Allocate this structure in your driver's probe():

    static int mydrv_probe(struct platform_device *pdev)
    {
        struct mydrv *mydrv;
    
        mydrv = devm_kzalloc(&pdev->dev, sizeof(*mydrv), GFP_KERNEL);
        mydrv->dev = &pdev->dev;
        platform_set_drvdata(pdev, mydrv);
    
        ...
    }
    

  • 创建show()/store()函数:

  • Create show() / store() functions:

    static ssize_t mydrv_myparam_show(struct device *dev,
            struct device_attribute *attr, char *buf)
    {
        struct mydrv *mydrv = dev_get_drvdata(dev);
        int len;
    
        len = sprintf(buf, "%d\n", mydrv->myparam);
        if (len <= 0)
            dev_err(dev, "mydrv: Invalid sprintf len: %d\n", len);
    
        return len;
    }
    
    static ssize_t mydrv_myparam_store(struct device *dev,
            struct device_attribute *attr, const char *buf, size_t count)
    {
        struct mydrv *mydrv = dev_get_drvdata(dev);
    
        kstrtol(buf, 10, &mydrv->myparam);
        return count;
    }
    

  • 为这些功能创建设备属性(在这些功能之后):

  • Create device attribute for those functions (right after those functions):

    static DEVICE_ATTR(myparam, S_IRUGO | S_IWUSR, mydrv_myparam_show,
                       mydrv_myparam_store);
    

  • 声明属性表(实际上为驱动程序列出了 sysfs文件):

    static struct attribute *mydrv_attrs[] = {
        &dev_attr_myparam.attr,
        NULL
    };
    

  • 声明属性组(实际上为驱动程序指定 sysfs目录):

    static struct attribute_group mydrv_group = {
        .name = "mydrv",
        .attrs = mydrv_attrs,
    };
    
    static struct attribute_group *mydrv_groups[] = {
        &mydrv_group,
        NULL
    }
    

    实际上可以替换为一行:

    which can be actually replaced with one line:

    ATTRIBUTE_GROUPS(mydrv);
    

  • 在驱动程序的probe()函数中创建sysfs目录和文件:

  • Create sysfs directory and files in your driver's probe() function:

    static int mydrv_probe(struct platform_device *pdev)
    {
        int ret;
    
        ...
    
        ret = sysfs_create_group(&pdev->dev.kobj, &mydrv_group);
        if (ret) {
            dev_err(&pdev->dev, "sysfs creation failed\n");
            return ret;
        }
    
        ...
    }
    

  • 在驱动程序的remove()函数中删除sysfs文件:

  • Remove your sysfs files in your driver's remove() function:

    static int mydrv_remove(struct platform_device *pdev)
    {
        sysfs_remove_group(&pdev->dev.kobj, &mydrv_group);
        ...
    }
    

  • 种族状况说明

    正如@FranzForstmayr正确指出的那样,在mydrv_probe()中添加带有sysfs_create_group()的sysfs文件时,可能存在竞赛条件.这是因为可以在调用mydrv_probe()之前就已经通知用户空间这些文件存在(这些文件实际上是由sysfs_create_group()函数创建的). Greg Kroah-Hartman的如何正确创建sysfs文件" 文章.

    Race condition note

    As @FranzForstmayr correctly pointed out, there may be race condition when adding sysfs files with sysfs_create_group() in mydrv_probe(). That's because user-space can be already notified that those files exist before mydrv_probe() called (where those files are actually being created by sysfs_create_group() function). This issue covered in details in "How to Create a sysfs File Correctly" article by Greg Kroah-Hartman.

    因此,在我们的platform_device情况下,您可以使用默认属性组,而不是调用sysfs_create_group()(及其对应的sysfs_remove_group()).为此,您需要将struct device的对应.groups字段分配给属性组变量:

    So in our case of platform_device, instead of calling sysfs_create_group() (and its counterpart sysfs_remove_group()), you can use default attribute group. To do so, you need to assign corresponding .groups field of your struct device to your attribute groups variable:

    static int mydrv_probe(struct platform_device *pdev)
    {
        ...
    
        pdev->dev.groups = mydrv_groups;
    
        ...
    }
    

    免责声明:由于请参阅[1,2,3]链接,以获取有关所提及种族状况的更多见解.

    See [1,2,3] links for more insights on mentioned race condition.

    有关更多示例,请在内核源目录中运行以下命令:

    For more examples, run next command in kernel source directory:

    $ git grep -l --all-match -e platform_device -e attribute -e '\.groups =' -- drivers/
    

    您还可以在提交消息中按默认属性"进行搜索:

    Also you can search by "default attribute" in commit messages:

    $ git log --no-merges --oneline --grep="default attribute" -- drivers/
    

    我发现有些提交是这样的:[4,5,6,7].

    Some commits I found this way: [4,5,6,7].

    [1] 我的属性太不讲究了,我该怎么办?

    [2] PATCH:sysfs:添加devm_sysfs_create_group()和朋友

    [3] [GIT PATCH] 3.11-rc2的驱动程序核心补丁

    [4] 提交1

    [5] 提交2

    [6] 提交3

    [7] 提交4

    这篇关于如何在平台驱动程序中将文件操作附加到sysfs属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆