这篇是最终章了,结束这一章后,对于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虚拟总线(三)最终章的更多相关文章

  1. 探究linux设备驱动模型之——platform虚拟总线(一)

    说在前面的话 :      设备驱动模型系列的文章主要依据的内核版本是2.6.32的,因为我装的Linux系统差不多就是这个版本的(实际上我用的fedora 14的内核版本是2.6.35.13的.) ...

  2. 探究linux设备驱动模型之——platform虚拟总线(二)

    上回说到,platform_match是驱动和设备之间的媒人婆,那么platform_match是如何匹配驱动和设备的呢?platform总线定义的匹配条件很简单,主要就是查看驱动结构体和设备结构体的 ...

  3. Linux设备驱动模型之platform(平台)总线详解

    /********************************************************/ 内核版本:2.6.35.7 运行平台:三星s5pv210 /*********** ...

  4. linux设备驱动模型之Kobject、kobj_type、kset【转】

    本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/74838165 版权声明:本文为博主原创文章,转载请注明http://blog.c ...

  5. Linux设备驱动模型简述(源码剖析)

    1. Linux设备驱动模型和sysfs文件系统 Linux内核在2.6版本中引入设备驱动模型,简化了驱动程序的编写.Linux设备驱动模型包含设备(device).总线(bus).类(class)和 ...

  6. Linux设备驱动模型底层架构及组织方式

    1.什么是设备驱动模型? 设备驱动模型,说实话这个概念真的不好解释,他是一个比较抽象的概念,我在网上也是没有找到关于设备驱动模型的一个定义,那么今天就我所学.所了解 到的,我对设备驱动模型的一个理解: ...

  7. LINUX设备驱动模型之class

    转自 https://blog.csdn.net/qq_20678703/article/details/52754661 1.LINUX设备驱动模型中的bus.device.driver,.其中bu ...

  8. Linux 设备驱动模型

    Linux系统将设备和驱动归一到设备驱动模型中了来管理 设备驱动程序功能: 1,对硬件设备初始化和释放 2,对设备进行管理,包括实参设置,以及提供对设备的统一操作接口 3,读取应用程序传递给设备文件的 ...

  9. linux设备驱动模型

    尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要. Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统 ...

随机推荐

  1. 8、Dubbo-配置(3)

    高可用 1.zookeeper宕机与dubbo直连 现象:zookeeper注册中心宕机,还可以消费dubbo暴露的服务. 原因: 健壮性 监控中心宕掉不影响使用,只是丢失部分采样数据 数据库宕掉后, ...

  2. ThinkPhp表单令牌和字段映射

    开启表单令牌: 先在配置文件目录下定义tags.php 在里面添加 return array( 'view_filter' =>array('Behavior\TokenBuildBehavio ...

  3. PAT——1074. 宇宙无敌加法器(20)

    地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的.而在PAT星人开挂的世界里,每个数字的每一位都是不同进制的,这种神奇的数字称为“PAT数”.每个PAT星人都必须熟记各位数字的进制表,例如 ...

  4. linux下安装perl

    1.在官网  http://www.perl.org/get.html  下载perl安装包 2.上传服务器并解压 3../Configure -des -Dprefix=安装目录 4.make&am ...

  5. js中的冒泡排序

    <!-- 冒泡排序:把一组数列按照一定的顺序进行排列,从大到小,或者从小到大 -->          // 控制循环的轮数          arr = [3,14,55,2,1,4,5 ...

  6. C++_构造函数与析构函数

    构造函数与析构函数 OOP第二课 1 构造函数 1.1 构造函数具有一些特殊的性质 1.2 定义构造函数的一般形式 1.3 利用构造函数创建对象 2 成员初始化表 3 缺省参数的构造函数 4 重载构造 ...

  7. mac 下安装php7.1 redis

    1.下载phpredis源文件 https://nodeload.github.com/nicolasff/phpredis/zip/master 下载后解压 2.执行命令 phpize  执行后执行 ...

  8. 【五】安装fcig

    安装fcig 安装fcig 此步骤是为了让spawn-fcgi能够识别自定义的demo 编译文件 自定义c文件 测试成功后,启动spawn cgi进行代理托管 此步骤是为了让spawn-fcgi能够识 ...

  9. PTA(BasicLevel)-1010 一元多项式求导

    一.题目和题意分析 设计函数求一元多项式的导数.x^n [n为整数] 的一阶导数为nx^(n−1). 输入格式: 以指数递降方式输入多项式非零项系数和指数(*绝对值均为不超过 1000 的整数*).数 ...

  10. 数据结构与算法之有序数组(2)——in dart

    本文比第一篇,采用了类实现.增加了运算符重载等功能.本来有序数组是不能修改某个位置的值的,因为这样会打破数组的有序性:但为了演示,保留了修改的方法,但为此增加了排序. import 'dart:mat ...