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
相关产品推荐
相关产品推荐

