探究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设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统 ...
随机推荐
- 为什么要使用GetSafeHwnd()函数
当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数,通过下面的例子来看其理由: CWnd *pwnd = FindWindow(“ ...
- Gradle Goodness: Renaming Files while Copying
With the Gradle copy task we can define renaming rules for the files that are copied. We use the ren ...
- oracle查询用户的权限
DBA_* 描述的是数据库中的所有对象 ALL_* 描述的是当前用户有访问权限的所有对象 USER_* 描述的是当前用户所拥有的所有对象 查看所有用户: select * from dba_user ...
- Oracle 自定义实用函数
一.ctod 字符转为date, create or replace function ctod(str in varchar2) return date as begin return to_dat ...
- Apache安装排错
今天安装一下Apache,发现报错,且在网上没有找到相关解决方法,所以记录一下 安装步骤:将下载好的apache包放置到要放置的目录中,最好是盘根目录下,然后命令行下进入到apache下面的bin目录 ...
- [HAOI2015]树上操作(树链剖分,线段树)
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 ...
- activemq的高级特性:通配符式分层订阅
activemq的高级特性之通配符式分层订阅 队列的名称可以分层:aa.bb.cc.dd 可以匹配:aa.bb.cc.dd,aa.*.cc.dd,aa.> *:匹配当前层的内容 >:任何一 ...
- 大数据时代的结构化存储--HBase
迄今,相信大家肯定听说过 HBase,但是对于 HBase 的了解可能仅仅是它是 Hadoop 生态圈重要的一员,是一个大数据相关的数据库技术. 今天我带你们一起领略一下 HBase 体系架构,看看它 ...
- Delphi XE7的蓝牙 Bluetooth
Delphi XE7已经内建了蓝牙功能,提供了System.Bluetooth.pas单元 顾名思义,System表示XE7的蓝牙功能可以在Windows,Android,IOS系统内使用 Syste ...
- Python2.6与Python2.7的format用法区别
Python2.6不支持format(123456L, ",")或format(123, ",")的format用法,会报下面的错误 ValueError: U ...