欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > dev_set_drvdata、dev_get_drvdata使用详解

dev_set_drvdata、dev_get_drvdata使用详解

2025/4/20 19:47:44 来源:https://blog.csdn.net/liuluyang530/article/details/147355622  浏览:    关键词:dev_set_drvdata、dev_get_drvdata使用详解

在Linux内核驱动开发中,dev_set_drvdata() 及相关函数用于管理设备驱动的私有数据,是模块化设计和数据隔离的核心工具。以下从函数定义、使用场景、示例及注意事项等方面进行详细解析:


一、函数定义与作用

  1. 核心函数

    • dev_set_drvdata() 和 dev_get_drvdata() 是操作设备私有数据的基础函数,直接通过 struct device 的 driver_data 成员实现数据存取:

      
      static inline void dev_set_drvdata(struct device *dev, void *data) {dev->driver_data = data;  // 将数据指针关联到设备:cite[2]:cite[6]
      }
      static inline void *dev_get_drvdata(const struct device *dev) {return dev->driver_data;  // 获取设备关联的数据指针:cite[6]
      }

  2. 设备类型封装函数
    针对不同设备类型(如平台设备、PCI设备、I2C设备),内核提供了封装函数以简化调用:

    • 平台设备platform_set_drvdata() 和 platform_get_drvdata()

      
      // 通过平台设备结构体间接调用核心函数
      static inline void platform_set_drvdata(struct platform_device *pdev, void *data) {dev_set_drvdata(&pdev->dev, data);  // 调用dev_set_drvdata:cite[1]:cite[2]
      }

    • I2C设备i2c_set_clientdata() 和 i2c_get_clientdata()

    • PCI设备pci_set_drvdata() 和 pci_get_drvdata()


二、使用场景与示例

  1. 典型应用场景

    • 驱动初始化(probe函数):在设备探测阶段分配并保存私有数据(如设备状态、配置信息)。

    • 资源释放(remove函数):在设备移除时获取数据并释放内存。

    • 多设备管理:通过私有数据区分不同设备实例,避免全局变量冲突。

  2. 代码示例
    平台设备驱动示例

    
    struct my_device_data {int config_param;char *buffer;
    };static int my_probe(struct platform_device *pdev) {struct my_device_data *data;data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);  // 动态分配内存:cite[3]if (!data) return -ENOMEM;// 初始化数据data->config_param = 100;platform_set_drvdata(pdev, data);  // 关联数据到设备:cite[2]return 0;
    }static int my_remove(struct platform_device *pdev) {struct my_device_data *data = platform_get_drvdata(pdev);  // 获取数据:cite[2]// 清理操作(如释放资源)return 0;
    }

    I2C设备驱动示例

    
    static int i2c_probe(struct i2c_client *client) {struct sensor_data *data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);i2c_set_clientdata(client, data);  // 通过封装函数设置数据:cite[6]return 0;
    }


三、注意事项

  1. 内存管理

    • 使用 devm_kzalloc() 等资源管理函数自动释放内存,避免内存泄漏。

    • 在 remove 函数中需检查数据有效性,防止空指针异常。

  2. 数据安全性

    • dev_get_drvdata() 返回的是原始指针,调用者需确保数据有效性(如避免在数据释放后访问)。

    • 多线程环境下需通过锁机制保护共享数据。

  3. 设备类型适配

    • 不同设备类型需使用对应的封装函数(如PCI设备用 pci_set_drvdata()),保证代码可读性和兼容性45。

  4. 数据存储范围

    • driver_data 应仅存储与设备实例相关的私有数据,避免混杂全局或无关信息。


四、扩展应用

  1. 复杂数据结构存储
    可通过将自定义结构体指针存入 driver_data,实现多层级数据管理。例如:

    
    struct complex_data {struct sub_data *sub;int status;
    };
    // 在probe中初始化并关联
    platform_set_drvdata(pdev, complex_data_ptr);

  2. 动态配置更新
    在运行时通过 dev_get_drvdata() 获取数据并修改参数,支持动态调整设备行为。


五、常见问题

  1. 为何不直接使用全局变量?

    • 全局变量无法区分多个设备实例,而 driver_data 天然支持多实例隔离,提升代码可维护性。

  2. 何时需要手动释放内存?

    • 若使用 kzalloc() 分配内存,需在 remove 函数中手动 kfree();若用 devm_kzalloc(),则由设备模型自动管理36。


通过合理使用 dev_set_drvdata() 及相关函数,开发者可以实现驱动数据的高效管理,提升代码的模块化和可维护性。具体实现需结合设备类型和内核版本调整(如不同内核中结构体定义可能略有差异)。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词