探究linux设备驱动模型之——platform虚拟总线(三)最终章
这篇是最终章了,结束这一章后,对于platform平台总线驱动的使用方法应该是能够无压力掌握。但是这一章涉及的内容会比前面两章多一些。
我们会一步一步地来完善上一章的例子。完善的目的是能够在应用层去控制我们写的这个驱动接口。
第一步,我们得先建立设备节点。看过ldd3(linux设备驱动程序 第三版)的人都知道设备节点是建立在/dev目录下的,但其实在/sys目录下也可以建立设备节点。我们接下来写的驱动使用后者的方法。sys文件系统是一个动态的文件系统,所谓动态即表明该文件系统的所有内容都是保存在内存里面而不是硬盘里面,所以该文件系统里面的内容不能永久保存,断电即消失。
在sys目录下面建立一个设备节点很简单,一般来说用到两个函数,一个是class_create,还有一个是device_create。这两个函数的配合使用在很多驱动程序里面都可以看到。下面给出这两个函数的原形:
class_create函数的原形在内核里面有些绕,我稍作了修改便如读者理解,如下所示:
struct class * class_create(struct module *owner,
const char *name)
第一个参数一般填入THIS_MODULE,第二个参数是给这个class起个名字,在sys目录下面有个class目录,假如我这样调用该函数:class_create(THIS_MODULE,"love");那么你将会在/sys/class目录下面看到一个文件名为love的新目录。
device_create的函数原型如下:
struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
这个函数原型比较复杂,我们一个一个地来说,第一个是前面介绍的class;第二个的用法到时看实际例子;第三个其实就是设备号,我们不打算在/dev目录下面建立设备节点,所以该参数也可以忽略;第四个是要传进去的私有数据,可以给他NULL;最后一个就是给这个device起名字,这个名字最后会成为新目录的文件名。
我们可以如下所示调用这两个函数:
struct class * love_class;
love_class = class_create(THIS_MODULE,"love");
device_create(love_class,NULL,0,NULL,"haoge");
这样名字为"haoge"的文件夹就会出现在/sys/class/love的目录下了。
第二步就是在/sys下面建立属性文件,所谓属性文件就是驱动程序提供给应用程序的控制接口。属性的数据结构如下:
struct attribute {
const char *name;
mode_t mode;
};
第一个参数当然是给这属性文件起一个文件名,第二个参数设置这个属性文件的读取权限。
但我们更多的是用device_attribute数据结构,如下所示:
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
};
可以看到attribute结构是device_attribute结构中的一个成员,另外两个成员函数就是对该属性文件进行读取的方法函数。
简单介绍完这些东西后,我们可以看一下最终修改的驱动代码,有三个文件:
第一个文件:
/****driver.c****/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <asm/system.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/mm.h>
struct haoge_data
{
char a[4096];
char * name;
struct device *dev;
}; struct class * haoge_class;
struct device * haoge_dev;
static ssize_t haoge_store(struct device *dev,
struct device_attribute *attr, char *buf,size_t size)
{
if(size>4096)
{
printk(KERN_ALERT "fuck you!");
return 0;
} return sprintf( ((struct haoge_data * )dev->platform_data)->a, buf);
}
static ssize_t haoge_show(struct device *dev,
struct device_attribute *attr, char *buf)
{ return sprintf(buf, ((struct haoge_data * )dev->platform_data)->a);
}
struct device_attribute dev_attr_brightness ={ \
.attr = {.name = "love", .mode = 0644 }, \
.show = haoge_show, \
.store = haoge_store,
\
};
static int haoge_probe(struct platform_device *dev)
{
struct haoge_data * p =(dev->dev).platform_data; haoge_dev =device_create(haoge_class, &(dev->dev), 0, NULL,
"%s", p->name);
p->dev=haoge_dev;
haoge_dev->platform_data=p;
device_create_file(haoge_dev, &dev_attr_brightness); printk(KERN_ALERT "%s",p->a); return 0;
} static int haoge_remove(struct platform_device *dev)
{ //和该驱动匹配的设备被卸载时便会调用haoge_remove函数,但是驱动本身卸载并不会调用
//该函数.
//所以要先卸载设备模块再卸载本驱动模块,否则device_unregister将无法被调用。
struct haoge_data * p =(dev->dev).platform_data;
device_remove_file(p->dev, &dev_attr_brightness);
device_unregister(p->dev); return 0;
} static struct platform_driver haoge_driver = {
.probe = haoge_probe,
.remove = haoge_remove,
.driver = {
.name = "haoge",
.owner = THIS_MODULE,
},
}; static int __init haoge_init(void)
{ haoge_class = class_create(THIS_MODULE,"haoge");
return platform_driver_register(&haoge_driver);
} static void __exit haoge_exit(void)
{ class_destroy(haoge_class);
platform_driver_unregister(&haoge_driver);
} module_init(haoge_init);
module_exit(haoge_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HaoGe");
第二个文件:
/****device1.c****/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <asm/system.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/mm.h>
struct haoge_data
{
char a[];
char * name;
};
struct haoge_data s ={
.name = "haoge_one",
}; struct platform_device haoge_device ={
.name= "haoge",
.id = ,
.dev = { .platform_data = &s,
},
}; static int __init haoge_init(void)
{
sprintf(s.a,"haogeverygood!\n"); platform_device_register(&haoge_device); return ;
} static void __exit haoge_exit(void)
{ platform_device_unregister(&haoge_device);
} module_init(haoge_init);
module_exit(haoge_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HaoGe");
第三个文件:
/****device2.c****/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <asm/system.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/mm.h>
struct haoge_data
{
char a[];
char * name;
};
struct haoge_data s ={
.name = "haoge_two",
}; struct platform_device haoge2_device ={
.name= "haoge",
.id = ,
.dev = {
.platform_data = &s,
},
}; static int __init haoge_init(void)
{
sprintf(s.a,"haoge very handsone!\n"); platform_device_register(&haoge2_device); return ;
} static void __exit haoge_exit(void)
{ platform_device_unregister(&haoge2_device);
} module_init(haoge_init);
module_exit(haoge_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HaoGe");
探究linux设备驱动模型之——platform虚拟总线(三)最终章的更多相关文章
- 探究linux设备驱动模型之——platform虚拟总线(一)
说在前面的话 : 设备驱动模型系列的文章主要依据的内核版本是2.6.32的,因为我装的Linux系统差不多就是这个版本的(实际上我用的fedora 14的内核版本是2.6.35.13的.) ...
- 探究linux设备驱动模型之——platform虚拟总线(二)
上回说到,platform_match是驱动和设备之间的媒人婆,那么platform_match是如何匹配驱动和设备的呢?platform总线定义的匹配条件很简单,主要就是查看驱动结构体和设备结构体的 ...
- Linux设备驱动模型之platform(平台)总线详解
/********************************************************/ 内核版本:2.6.35.7 运行平台:三星s5pv210 /*********** ...
- linux设备驱动模型之Kobject、kobj_type、kset【转】
本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/74838165 版权声明:本文为博主原创文章,转载请注明http://blog.c ...
- Linux设备驱动模型简述(源码剖析)
1. Linux设备驱动模型和sysfs文件系统 Linux内核在2.6版本中引入设备驱动模型,简化了驱动程序的编写.Linux设备驱动模型包含设备(device).总线(bus).类(class)和 ...
- Linux设备驱动模型底层架构及组织方式
1.什么是设备驱动模型? 设备驱动模型,说实话这个概念真的不好解释,他是一个比较抽象的概念,我在网上也是没有找到关于设备驱动模型的一个定义,那么今天就我所学.所了解 到的,我对设备驱动模型的一个理解: ...
- LINUX设备驱动模型之class
转自 https://blog.csdn.net/qq_20678703/article/details/52754661 1.LINUX设备驱动模型中的bus.device.driver,.其中bu ...
- Linux 设备驱动模型
Linux系统将设备和驱动归一到设备驱动模型中了来管理 设备驱动程序功能: 1,对硬件设备初始化和释放 2,对设备进行管理,包括实参设置,以及提供对设备的统一操作接口 3,读取应用程序传递给设备文件的 ...
- linux设备驱动模型
尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要. Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统 ...
随机推荐
- Kali-linux分析密码
在实现密码破解之前,介绍一下如何分析密码.分析密码的目的是,通过从目标系统.组织中收集信息来获得一个较小的密码字典.本节将介绍使用Ettercap工具或MSFCONSOLE来分析密码. 8.2.1 E ...
- No.7 - 使用 animate.css 实现一个优雅的登录框
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content ...
- jmeter接口测试3-正则表达式提取器的使用
正则表达式的用处很多,最基础的用法 1,断言 2,传参(关联) 例子 1.http请求 2正则表达式提取,想要提取列表列中id,一遍打开列表页 如果是1,每次就会取相同的值!匹配数字的权限高于模板$0 ...
- PAT——1051. 复数乘法
复数可以写成(A + Bi)的常规形式,其中A是实部,B是虚部,i是虚数单位,满足i2 = -1:也可以写成极坐标下的指数形式(R*e(Pi)),其中R是复数模,P是辐角,i是虚数单位,其等价于三角形 ...
- [LuoguP1360][USACP07MAR]黄金阵容均衡
[LuoguP1360][USACP07MAR]黄金阵容均衡(Link) 每天会增加一个数\(A\),将\(A\)二进制分解为\(a[i]\),对于每一个\(i\)都增加\(a[i]\),如果一段时间 ...
- CC2640R2F&TI-RTOS 拿到 TI CC2640R2F 开发板 第三件事就是使用 TI-RTOS 创建 一个任务 和 使用 信号量 超时来闪烁 LED灯
/* * data_process.c * * Created on: 2018年7月5日 * Author: admin */ #include <ti/sysbios/knl/Task.h& ...
- JSON在Java中的使用(一)
1.去JSON官网下载org.json包 https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.json%22%20AND%20a%3A%22 ...
- 前端基础-BOM和DOM的介绍
阅读目录 BOM和DOM的简述 DOM详细操作 事件 一.BOM和DOM的简述 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我 ...
- MySql 5.7.21免安装版本win10下的配置
1.解压到想要安装的位置,创建my.ini文件 my.ini的内容如下 [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [mysqld] #设 ...
- Redis之Redis事务
Redis事务的概念: Redis 事务的本质是一组命令的集合.事务支持一次执行多个命令,一个事务中所有命令都会被序列化.在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会 ...