gpt4 book ai didi

linux-kernel - 如何将文件操作附加到平台驱动程序中的 sysfs 属性?

转载 作者:行者123 更新时间:2023-12-04 09:30:36 25 4
gpt4 key购买 nike

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

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

我的属性结构如下所示:

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

我使用此调用注册文件:

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

最佳答案

归结为下一个:

  • 重用来自 struct device 的现有 kobject (来自您的 struct platform_device )为 sysfs_create_group() (而不是创建自己的 kobject )
  • 使用 DEVICE_ATTR()申报struct device_attribute而不是常规的 __ATTR() ,从而创建 struct kobj_attribute .

  • 以下是我为平台驱动程序创建 sysfs 属性的方法。
  • show() 中创建您将用作私有(private)数据的结构/store() sysfs 属性(文件)的操作。例如:

    struct mydrv {
    struct device *dev;
    long myparam;
    };
  • 在驱动程序的 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()职能:

    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;
    }
  • 为这些功能创 build 备属性(就在这些功能之后):

    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
    }

    实际上可以用一行替换:

    ATTRIBUTE_GROUPS(mydrv);
  • 在驱动程序的probe() 中创建sysfs 目录和文件功能:

    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 文件功能:

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

  • 比赛条件说明

    正如@FranzForstmayr 正确指出的那样,可能有 比赛条件 使用 sysfs_create_group() 添加 sysfs 文件时在 mydrv_probe() .这是因为在 mydrv_probe() 之前已经可以通知用户空间这些文件存在。调用(这些文件实际上是由 sysfs_create_group() 函数创建的)。 "How to Create a sysfs File Correctly" 中详细介绍了此问题Greg Kroah-Hartman 的文章。

    所以在我们的 platform_device 的例子中, 而不是调用 sysfs_create_group() (及其对应的 sysfs_remove_group() ),您可以使用 默认属性组 .为此,您需要分配相应的 .groups您的 struct device 的字段到您的属性组变量:

    static int mydrv_probe(struct platform_device *pdev)
    {
    ...

    pdev->dev.groups = mydrv_groups;

    ...
    }

    免责声明 : 我没有测试这段代码,虽然它应该可以工作,因为 this代码。

    请参阅 [1,2,3] 链接以获取有关上述竞争条件的更多见解。

    有关更多示例,请在内核源目录中运行下一个命令:
    $ git grep -l --all-match -e platform_device -e attribute -e '\.groups =' -- drivers/

    您还可以在提交消息中按“默认属性”搜索:
    $ git log --no-merges --oneline --grep="default attribute" -- drivers/

    我以这种方式发现了一些提交:[4,5,6,7]。

    引用

    [1] My attributes are way too racy, what should I do?

    [2] PATCH: sysfs: add devm_sysfs_create_group() and friends

    [3] [GIT PATCH] Driver core patches for 3.11-rc2

    [4] commit 1

    [5] commit 2

    [6] commit 3

    [7] commit 4

    关于linux-kernel - 如何将文件操作附加到平台驱动程序中的 sysfs 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37237835/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com