You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux 6.6内核下如何为I2C设备提供固定的用户空间访问路径?

解决方案

方案1:内核驱动中创建固定独立sysfs目录

这种方法直接在内核驱动中创建一个固定路径的sysfs目录,将设备属性暴露到该目录下,彻底脱离I2C设备地址相关的路径。

设备树配置

给I2C设备节点指定唯一的compatible字符串,确保驱动能稳定匹配,不受地址变更影响:

&i2c0 {
    status = "okay";
    special-device@57 {
        compatible = "my,unique-device"; // 自定义唯一兼容字符串
        reg = <0x57>; // 地址可随配置修改
        // 其他设备相关属性
    };
};

驱动代码修改

在驱动的probe函数中创建固定sysfs目录,并将属性组挂载到该目录:

#include <linux/kobject.h>
#include <linux/i2c.h>
#include <linux/sysfs.h>

// 定义你的设备属性组(原有的属性定义保留)
static struct attribute *my_dev_attrs[] = {
    // 你的属性项,比如:
    &dev_attr_my_attr.attr,
    NULL,
};
ATTRIBUTE_GROUPS(my_dev);

static struct kobject *fixed_kobj;

static int my_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct my_dev_data *data;

    // 分配并初始化设备私有数据
    data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;
    i2c_set_clientdata(client, data);

    // 在/sys/下创建固定目录"my_fixed_device"
    fixed_kobj = kobject_create_and_add("my_fixed_device", kernel_kobj);
    if (!fixed_kobj) {
        dev_err(&client->dev, "Failed to create fixed sysfs kobject\n");
        return -ENOMEM;
    }

    // 将属性组添加到固定目录
    if (sysfs_create_group(fixed_kobj, &my_dev_group)) {
        dev_err(&client->dev, "Failed to add sysfs group to fixed dir\n");
        kobject_put(fixed_kobj);
        return -ENOMEM;
    }

    // 可选:创建指向原I2C设备节点的符号链接,方便调试
    sysfs_create_link(fixed_kobj, &client->dev.kobj, "i2c_device");

    return 0;
}

static void my_dev_remove(struct i2c_client *client)
{
    // 清理sysfs资源
    sysfs_remove_group(fixed_kobj, &my_dev_group);
    kobject_put(fixed_kobj);
}

// 驱动匹配表(绑定compatible字符串)
static const struct of_device_id my_dev_of_match[] = {
    { .compatible = "my,unique-device" },
    { /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, my_dev_of_match);

static struct i2c_driver my_dev_driver = {
    .driver = {
        .name = "my_unique_device",
        .of_match_table = my_dev_of_match,
    },
    .probe = my_dev_probe,
    .remove = my_dev_remove,
};
module_i2c_driver(my_dev_driver);

完成后,用户空间可通过/sys/my_fixed_device/直接访问设备属性,不受I2C地址变化影响。

方案2:修改设备名称生成固定sysfs链接

通过修改I2C客户端设备的名称,让sysfs自动生成固定名称的链接指向实际设备节点。

驱动代码修改

在probe函数中调用dev_set_name设置固定设备名称:

static int my_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct my_dev_data *data;

    data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
    if (!data)
        return -ENOMEM;
    i2c_set_clientdata(client, data);

    // 设置固定设备名称,确保系统唯一
    dev_set_name(&client->dev, "my_fixed_i2c_device");

    // 原有的属性注册逻辑保留(比如sysfs_create_group(&client->dev.kobj, &my_dev_group))

    return 0;
}

此时,sysfs会在/sys/bus/i2c/devices/下生成my_fixed_i2c_device符号链接,指向实际的0-00xx设备节点。用户空间直接访问/sys/bus/i2c/devices/my_fixed_i2c_device/即可。

方案3:用户空间udev规则创建固定链接

如果不想修改内核驱动,可通过udev规则在用户空间生成固定路径的符号链接。

编写udev规则

创建/etc/udev/rules.d/99-my-device.rules文件,内容如下:

SUBSYSTEM=="i2c", ATTR{of_node/compatible}=="my,unique-device", SYMLINK+="my_fixed_device"

当设备枚举时,udev会自动在/dev/下创建my_fixed_device符号链接,同时也可通过该链接关联到对应的sysfs路径。


内容的提问来源于stack exchange,提问作者bielu000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:43:12