Linux设备驱动的class(类)的理解(以timed_output为基础).docx_第1页
Linux设备驱动的class(类)的理解(以timed_output为基础).docx_第2页
Linux设备驱动的class(类)的理解(以timed_output为基础).docx_第3页
Linux设备驱动的class(类)的理解(以timed_output为基础).docx_第4页
Linux设备驱动的class(类)的理解(以timed_output为基础).docx_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux设备驱动的class(类)的理解(以timed_output为基础)一、 前言前天写了关于安卓震动系统的驱动开发全过程,其中用到了timed_output这个驱动模型,那天只是简单的用了一下,今天拿出来彻底的研究一下,分享一下我的理解。在使用这个驱动模型的时候,我一直都很奇怪,它的名字看上去和时间有很大的关系,在我的心里我也以为它会提供一些与时间操作相关的函数,帮助开发人员简单的完成与时间相关的操作,但是翻遍了它的实现代码都没有发现它与时间的半毛钱关系。真坑爹!面对这么坑爹的一个驱动模型,我很想知道,它是linux kernel原来就带的呢,还是android为linux kernel添加的,首先我看到它的实现代码timed_output.c所在的目录drivers/staging/android,比较明显这个是android为linux kernel添加的,再打开文件看它的版权*Copyright (C) 2009 Google, Inc.* Author: Mike Lockwood name | !tdev-enable | !tdev-get_time)return -EINVAL;/如果timed_output 类没有注册的话,就从这里注册,也就是说要使用timed_output驱动/框架不用module_init(timed_output_init);也是可以的ret = create_timed_output_class();if (ret index = atomic_inc_return(&device_count);/创建设备tdev-dev = device_create(timed_output_class, NULL,MKDEV(0, tdev-index), NULL, tdev-name);if (IS_ERR(tdev-dev)return PTR_ERR(tdev-dev);/创建enable设备文件/这里有个参数dev_attr_enable结构体,是由/static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);/这个宏创建的ret = device_create_file(tdev-dev, &dev_attr_enable);if (ret dev, tdev);tdev-state = 0;return 0;err_create_file:device_destroy(timed_output_class, MKDEV(0, tdev-index);printk(KERN_ERR timed_output: Failed to register driver %sn,tdev-name);return ret;void timed_output_dev_unregister(struct timed_output_dev *tdev)/这个函数很简单不做说明device_remove_file(tdev-dev, &dev_attr_enable);device_destroy(timed_output_class, MKDEV(0, tdev-index);dev_set_drvdata(tdev-dev, NULL);3. Enable的读写函数static ssize_t enable_show(struct device *dev, struct device_attribute *attr,char *buf)struct timed_output_dev *tdev = dev_get_drvdata(dev);int remaining = tdev-get_time(tdev);return sprintf(buf, %dn, remaining);static ssize_t enable_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size)struct timed_output_dev *tdev = dev_get_drvdata(dev);int value;if (sscanf(buf, %d, &value) != 1)return -EINVAL;tdev-enable(tdev, value);return size;static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);这几个函数都很简单不做说明三、 Class理解看完上面的代码,觉得还是非常好理解的,唯一不懂的就是上面class创建删除,device创建删除的具体实现。class是设备驱动中很重要的一块,下面是从LDD3中关于class的说明:一个类是一个设备的高级视图, 它抽象出低级的实现细节. 驱动可以见到一个SCSI 磁盘或者一个 ATA 磁盘, 在类的级别, 它们都是磁盘. 类允许用户空间基于它们做什么来使用设备, 而不是它们如何被连接或者它们如何工作.几乎所有的类都在 sysfs 中在 /sys/class 下出现. 因此, 例如, 所有的网络接口可在 /sys/class/net 下发现, 不管接口类型.输入设备可在 /sys/class/input 下, 以及串行设备在 /sys/class/tty. 一个例外是块设备, 由于历史的原因在 /sys/block.类成员关系常常由高级的代码处理, 不必要驱动的明确的支持.我的理解是类就是 设备的分类,通过特定的实现方法,系统把设备分成一定的类,类里面每个设备生成自己的设备文件,提供给上层调用。关于class的创建和删除本来想自己写的,但是在网上看到skywang12345大神一个特别好的文章先把地址贴过来/skywang12345/archive/2013/05/15/driver_class.html下面是具体内容复制粘贴的。 (本人属于转载!)linux中class_create和class_register说明本文介绍linux中class_create和class_register的相关使用方法1 class结构体介绍 内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create()函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create()函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create()函数,去/sysfs下寻找对应的类从而创建设备节点。2 class相关API说明如下表:3 class_create()使用示例示例一,通过class_create()、class_destroy()去注册和注销/sys/class/my_char_dev代码如下: 1 #include 2 #include 3 #include 4 5 struct class *mem_class; 6 7 static int _init class_create_destroy_init(void) 8 9 / class_create动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加到内核中。创建的逻辑类位于/sys/class/。10 / 参数:11 / owner, 拥有者。一般赋值为THIS_MODULE。12 / name, 创建的逻辑类的名称。13 mem_class = class_create(THIS_MODULE, my_char_dev);14 if (mem_class=NULL)15 16 printk( create class failed!n);17 return -1;18 19 20 return 0;21 22 23 static void _exit class_create_destroy_exit(void)24 25 if (mem_class != NULL) 26 27 class_destroy(mem_class);28 mem_class = NULL;29 30 31 32 33 module_init(class_create_destroy_init);34 module_exit(class_create_destroy_exit);35 36 MODULE_LICENSE(GPL);4 class_register()使用示例示例二,通过class_register()、class_unregister()去注册和注销/sys/class/my_char_dev代码如下: 1 #include 2 #include 3 #include 4 #include 5 6 #define CLASS_NAME my_char_dev 7 struct class *mem_class; 8 9 static void class_create_release (struct class *cls)10 11 printk(%sn, _func_ );12 kfree(cls);13 14 15 static int _init class_create_destroy_init(void)16 17 printk(%sn, _func_);18 19 int ret;20 21 / 申请class结构体内存22 mem_class = kzalloc(sizeof(*mem_class), GFP_KERNEL);23 if (mem_class = NULL) 24 25 printk(create mem class failed!n);26 return -1;27 28 printk(create mem class successn);29 30 mem_class-name = CLASS_NAME;31 mem_class-owner = THIS_MODULE;32 / 注销时class时的回调函数,在此回调函数中释放之前所分配的class结构体内存33 mem_class-class_release = class_create_release;34 35 / 将class注册到内核中,同时会在/sys/class/下创建class对应的节点36 int retval = class_register(mem_class);37 if (ret) 38 39 printk(class_register failed!n);40 kfree(mem_class);41 return -1; 42 43 printk(class_register successn);44 45 46 return 0;47 48 49 static void _exit class_create_destroy_exit(void)50 51 printk(%sn, _func_);52 53 if (mem_class != NULL) 54 55 class_unregister(mem_class);56 mem_class = NULL;57 58 59 60 module_init(class_create_destroy_init);61 module_exit(class_create_destroy_exit);62 63 MODULE_LICENSE(GPL);附录一,class_create()和class_register()对比实际上,示例一和示例二是等价的。具体的可以通过查看class_create()和class_register()、class_destroy()和class_unregister()的源码去验证。class_register()的代码如下:1 / 将class注册到/sys/class/中2 #define class_register(class) 3 ( 4 static struct lock_class_key _key; 5 _class_register(class, &_key); 6 )class_register()是通过调用_class_register()来注册到sysfs中的。_class_register()的代码如下: 1 int _class_register(struct class *cls, struct lock_class_key *key) 2 3 struct class_private *cp; 4 int error; 5 6 pr_debug(device class %s: registeringn, cls-name); 7 8 cp = kzalloc(sizeof(*cp), GFP_KERNEL); 9 if (!cp) 10 return -ENOMEM; 11 klist_init(&cp-class_devices, klist_class_dev_get, klist_class_dev_put); 12 INIT_LIST_HEAD(&cp-class_interfaces); 13 kset_init(&cp-class_dirs); 14 _mutex_init(&cp-class_mutex, struct class mutex, key); 15 error = kobject_set_name(&cp-class_subsys.kobj, %s, cls-name); 16 if (error) 17 kfree(cp); 18 return error; 19 20 21 /* set the default /sys/dev directory for devices of this class */ 22 if (!cls-dev_kobj) 23 cls-dev_kobj = sysfs_dev_char_kobj; 24 25 #if defined(CONFIG_SYSFS_DEPRECATED) & defined(CONFIG_BLOCK) 26 /* let the block class directory show up in the root of sysfs */ 27 if (cls != &block_class) 28 cp-class_subsys.kobj.kset = class_kset; 29 #else 30 cp-class_subsys.kobj.kset = class_kset; 31 #endif 32 cp-class_subsys.kobj.ktype = &class_ktype; 33 cp-class = cls; 34 cls-p = cp; 35 36 / 将class注册到内核中37 error = kset_register(&cp-class_subsys); 38 if (error) 39 kfree(cp); 40 return error; 41 42 error = add_class_attrs(class_get(cls); 43 class_put(cls); 44 return error; 45 class_unregister()的代码如下:1 void class_unregister(struct class *cls) 2 3 pr_debug(device class %s: unregisteringn, cls-name); 4 remove_class_attrs(cls); 5 / 将class从内核中注销6 kset_unregister(&cls-p-class_subsys); 7 下面,我们查看class_create()、class_destroy()的相关代码。class_create()的代码如下:1 #define class_create(owner, name) 2 ( 3 static struct lock_class_key _key; 4 _class_create(owner, name, &_key); 5 )class_create()是通过调用_class_create()注册到内核中的。_class_create()的代码如下: 1 struct class *_class_create(struct module *owner, const char *name, 2 struct lock_class_key *key) 3 4 struct class *cls; 5 int retval; 6 7 / 分配class结构体 8 cls = kzalloc(sizeof(*cls), GFP_KERNEL); 9 if (!cls) 10 retval = -ENOMEM; 11 goto error; 12 13 14 cls-name = name; 15 cls-owner = owner; 16 / class对应的释放函数,在class从内核中注销时会执行该函数17 cls-class_release = class_create_release; 18 19 / 通过调用_class_register()将class注册到内核中20 retval = _class_register(cls, key); 21 if (retval) 22 goto error; 23 24 return cls; 25 26 error: 27 kfree(cls); 28 return ERR_PTR(retval); 29 class_create_release的代码如下:1 static void class_create_release(struct class *cls) 2 3 pr_debug(%s called for %sn, _func_, cls-name); 4 / 释

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论