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

内核模块对接DS24xxx 1-Wire设备,实现用户空间可访问解码功能咨询

问题解答

为什么用filp_open()读取sysfs是错误的方式

  • 内核中严格不推荐使用用户态风格的文件IO操作(比如filp_open()/vfs_read()),这会破坏内核的上下文模型,甚至可能引发死锁、资源泄漏等问题。
  • sysfs的节点并非普通磁盘文件,其背后是内核的sysfs_ops接口,依赖用户态上下文才能正确工作,内核态直接调用文件操作函数大概率会失败,这就是你读取数据失败的核心原因。

最优实现方案:基于Linux 1-Wire子系统开发驱动模块

Linux内核已经内置了成熟的1-Wire子系统,你应该直接对接该子系统,而非通过sysfs中转。这种方式更符合内核驱动的设计规范,性能和稳定性也更有保障:

核心思路

  1. 注册1-Wire设备驱动:实现w1_driver结构体,当系统枚举到你的DS24xxx设备时,probe函数会被触发,你可以在这里获取设备句柄。
  2. 直接调用1-Wire API访问硬件:使用子系统提供的w1_read_block()、w1_write_block()等函数,直接读取EEPROM数据,无需通过sysfs。
  3. 暴露解码接口给用户空间:通过字符设备(cdev)或sysfs节点,将解码后的数据提供给用户态应用。

简化代码示例

#include <linux/w1.h>
#include <linux/cdev.h>
#include <linux/fs.h>

// 自定义设备结构体,保存1-Wire slave句柄和字符设备信息
struct ds24xxx_decoder_dev {
    struct w1_slave *slave;
    struct cdev cdev;
    dev_t dev_num;
};

static struct class *decoder_class;
static struct ds24xxx_decoder_dev *decoder_dev;

// 用户空间读取解码数据的回调
static ssize_t decode_data_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
    struct ds24xxx_decoder_dev *dev = filp->private_data;
    u8 eeprom_data[64]; // 根据你的DS24xxx设备容量调整
    char decoded_buf[256];
    int ret, decoded_len;

    // 调用1-Wire子系统API读取EEPROM
    ret = w1_read_block(dev->slave, eeprom_data, sizeof(eeprom_data));
    if (ret < 0)
        return ret;

    // 这里添加你的解码逻辑,将eeprom_data转换为可读的decoded_buf
    // 示例:简单转成十六进制字符串
    decoded_len = scnprintf(decoded_buf, sizeof(decoded_buf), "%ph\n", eeprom_data);

    // 将解码后的数据拷贝到用户空间
    return simple_read_from_buffer(buf, count, ppos, decoded_buf, decoded_len);
}

// 文件操作结构体
static const struct file_operations decoder_fops = {
    .owner = THIS_MODULE,
    .read = decode_data_read,
    .open = simple_open,
};

// 1-Wire设备probe回调,设备枚举时触发
static int ds24xxx_decoder_probe(struct w1_slave *slave)
{
    int ret;

    decoder_dev = devm_kzalloc(&slave->dev, sizeof(*decoder_dev), GFP_KERNEL);
    if (!decoder_dev)
        return -ENOMEM;

    decoder_dev->slave = slave;
    dev_set_drvdata(&slave->dev, decoder_dev);

    // 申请字符设备号
    ret = alloc_chrdev_region(&decoder_dev->dev_num, 0, 1, "ds24xxx-decoder");
    if (ret < 0)
        return ret;

    // 初始化字符设备
    cdev_init(&decoder_dev->cdev, &decoder_fops);
    decoder_dev->cdev.owner = THIS_MODULE;
    ret = cdev_add(&decoder_dev->cdev, decoder_dev->dev_num, 1);
    if (ret < 0) {
        unregister_chrdev_region(decoder_dev->dev_num, 1);
        return ret;
    }

    // 创建设备节点,方便用户空间访问
    device_create(decoder_class, &slave->dev, decoder_dev->dev_num, NULL, "ds24xxx-decoder");

    return 0;
}

// 1-Wire设备remove回调
static void ds24xxx_decoder_remove(struct w1_slave *slave)
{
    struct ds24xxx_decoder_dev *dev = dev_get_drvdata(&slave->dev);

    device_destroy(decoder_class, dev->dev_num);
    cdev_del(&dev->cdev);
    unregister_chrdev_region(dev->dev_num, 1);
}

// 1-Wire驱动结构体,替换为你的DS24xxx设备家族ID
static struct w1_driver ds24xxx_decoder_driver = {
    .driver = {
        .name = "ds24xxx-decoder",
        .owner = THIS_MODULE,
    },
    .probe = ds24xxx_decoder_probe,
    .remove = ds24xxx_decoder_remove,
    .id = W1_FAMILY_DS2430, // 示例:DS2430的家族ID,根据你的设备修改
};

static int __init ds24xxx_decoder_init(void)
{
    int ret;

    decoder_class = class_create(THIS_MODULE, "ds24xxx-decoder");
    if (IS_ERR(decoder_class))
        return PTR_ERR(decoder_class);

    ret = w1_register_driver(&ds24xxx_decoder_driver);
    if (ret < 0) {
        class_destroy(decoder_class);
        return ret;
    }

    return 0;
}
module_init(ds24xxx_decoder_init);

static void __exit ds24xxx_decoder_exit(void)
{
    w1_unregister_driver(&ds24xxx_decoder_driver);
    class_destroy(decoder_class);
}
module_exit(ds24xxx_decoder_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("DS24xxx EEPROM Decoder Driver");
MODULE_AUTHOR("Your Name");

更简单的替代方案:用户空间实现解码

如果你只是需要快速验证功能,或者不想深入内核开发,完全可以在用户空间编写程序:

  • 直接读取/sys/bus/w1/devices/w1_bus_master1/下的设备节点数据。
  • 在用户空间完成数据解码逻辑,避免内核开发的复杂性。

这种方案对于新手来说门槛更低,无需处理内核的内存管理、锁机制等细节,调试也更方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:41:03