设为首页 收藏本站
查看: 786|回复: 0

[经验分享] Linux驱动框架----hwmon

[复制链接]

尚未签到

发表于 2015-3-8 16:12:08 | 显示全部楼层 |阅读模式
  写在前面的话:
  对于框架,我觉得就是在一定规范的形式下去实现你要的功能。这里就涉及到一个变与不变的地方。你所要实现的功能会是千差万别的---这就是变的地方,而所谓既定的规范,包括建立目录和属性文件这是Linux系统已经为我们做好了的,我们只需要直接拿来引用就OK了。
  那么今天,我们就来看看hwmon框架是怎么样的。

  对hwmon而言,它是sysfs框架下的一个类,但是所有有关该类与sys的接口都已经在drivers/hwmon/hwmon.c实现,因而我们也不必过多的关心。
  那么我们到底要做些什么呢?
  对于你要实现的功能部分,你就自己去想象吧,下面我们来说说在我们的程序中对于不变的那部分要如何去实现。
  我就以最基本的读CPU温度的程序为例,来说明整个框架的编写。
  一.作为驱动,首先我们要做就是驱动的注册和撤销。
  因此,在XXX_hwmon_init()函数中对hwmon驱动和该驱动的属性文件等进行注册。
  my_hwmon_dev = hwmon_device_register(NULL);
  ret = sysfs_create_group(&my_hwmon_dev->kobj,&my_hwmon_attribute_group);
  ret = create_sysfs_temp_files(&my_hwmon_dev->kobj);
  在有这么多的注册函数时,对于函数的异常处理,我个人觉得用goto来实现,比较直观和易用,让人看起来一目了然。

1 static int __init my_hwmon_init(void)
2 {
3         int ret;
4
5         printk(KERN_INFO "my cpu temperature hwmon enter!\n");
6
7         my_hwmon_dev = hwmon_device_register(NULL);
8         if (IS_ERR(my_hwmon_dev)) {
9                 ret = -ENOMEM;
10                 printk(KERN_ERR "my_hwmon_device_register fail!\n");
11                 goto fail_hwmon_device_register;
12         }
13
14         ret = sysfs_create_group(&my_hwmon_dev->kobj,
15                                 &my_hwmon_attribute_group);
16         if (ret) {
17                 printk(KERN_ERR "fail to create my hwmon!\n");
18                 goto fail_create_group_hwmon;
19         }
20
21         ret = create_sysfs_temp_files(&my_hwmon_dev->kobj);
22         if (ret) {
23                 printk(KERN_ERR "fail to create temperature files!\n");
24                 goto fail_create_sysfs_temp_files;
25         }
26         return ret;
27
28 fail_create_sysfs_temp_files:
29         sysfs_remove_group(&my_hwmon_dev->kobj, &my_hwmon_attribute_group);
30 fail_create_group_hwmon:
31         hwmon_device_unregister(my_hwmon_dev);
32 fail_hwmon_device_register:
33         return ret;
34 }
  而在XXX_hwmon_exit()函数中,和XXX_hwmon_init()函数相对应的,以相反的顺序对已注册的设备进行撤销。
  remove_sysfs_temp_files(&my_hwmon_dev->kobj);
  sysfs_remove_group(&my_hwmon_dev->kobj,&my_hwmon_attribute_group);
  hwmon_device_unregister(my_hwmon_dev);
  好了,至此,hwmon架构的初始化和撤销的工作已经完成。
  二.接下去就是对hwmon下的各种属性文件的创建和对温度的读写。
  1.hwmon整体属性框架
  总的来讲分为三部曲:
  首先,每个hwmon设备都会有自己独有的属性,这些独有属性就被SENSOR_DEVICE_ATTR声明为struct attribute结构体。
  SENSOR_DEVICE_ATTR具体定义在include/linux/hwmon-sysfs.h中:

1 #define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
2
3 struct sensor_device_attribute sensor_dev_attr_##_name          \
4
5         = SENSOR_ATTR(_name, _mode, _show, _store, _index)
  在程序中,则被写作:

1 static SENSOR_DEVICE_ATTR(name, S_IRUGO, get_my_hwmon_name, NULL, 0);
  然后,加入到sysfs框架的struct attribute属性结构体数组中,注意该结构体数组最后一项必须以NULL结尾。
  struct attribute定义在include/linux/sysfs.h中。

1 static struct attribute *my_hwmon_attributes[] = {
2         &sensor_dev_attr_name.dev_attr.attr,
3         NULL,
4 };
  最后,将这些众多的属性汇总到结构struct attribute_group中。这个struct attribute_group被sysfs_create_group()函数调用建立整个属性框架。
  struct attribute_group定义在include/linux/sysfs.h中。

1 static struct attribute_group my_hwmon_attribute_group = {
2         .attrs = my_hwmon_attributes,
3 };
  在我的程序中,这里只有一个属性—name,表示该hwmon驱动的名称。
  2.温度相关属性文件的建立
  在上面,整个hwmon的框架已经建立,接下来就是温度的读取,显示。这个过程其实是sysfs框架的内容。
  首先,确定会有多少属性,每个属性文件都会被SENSOR_DEVICE_ATTR声明为struct attribute结构体。其中的_show和_store是以函数形式实现,因此对应的实现相应的函数,若没有这个功能的实现就以NULL代替;
  _show表示的是从属性文件中读取出数据。
  _store表示的是向属性文件中写入数据。
  因此,如果该属性文件是不可写是,_store实现为NULL。
  然后,将同一seneor的属性加入到sysfs框架的struct attribute属性结构体数组中,注意该结构体数组最后一项必须以NULL结尾,被sysfs_create_files()函数调用。
  以上两步是建立属性文件最基本的两步,我们的具体功能可以在_show和_store两个函数中去实现。当然对于一些复杂的设备来讲仅仅这两步是不够的,如果该设备属于平台驱动或者是某一大类设备,如I2C,我们此时就需要根据具体情况去声明相应的结构,并按照相应结构的规范去操作。
  在我的程序中仅限于前两步,因为程序中并未涉及到任何其他设备,只是简单的读取了温度寄存器。程序中定义了两个属性my_cpu_temp_label和get_my_cpu_temp。
  下面是我模块在加载后生成目录的tree型图:
   DSC0000.png
  这些就是我对hwmon框架在目前基础上的了解。
  最后向大家做个推荐啊:我的所有程序都会在github上,所以,大家要是有兴趣的话,可以去github上去clone。
  我的github地址为:https://github.com/Antonio-Zhou
  这篇文章中完整代码的下载方式为:git clone git://github.com/Antonio-Zhou/LoongsonDriver.git
  下载之后,其中会有一个cpu_temp的目录,里面存放着makefile文件和源代码。
  希望大家多多提意见哦!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-44541-1-1.html 上篇帖子: linux-gcc 编译时头文件和库文件搜索路径 下篇帖子: 红帽Linux.5.5企业版本在VM虚拟机里中文乱码的解决方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表