探究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设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统 ...
随机推荐
- [Python 多线程] Lock、阻塞锁、非阻塞锁 (八)
线程同步技术: 解决多个线程争抢同一个资源的情况,线程协作工作.一份数据同一时刻只能有一个线程处理. 解决线程同步的几种方法: Lock.RLock.Condition.Barrier.semapho ...
- 401. Binary Watch 回溯
A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom ...
- 关于tomcat无法启动问题详解
通常情况tomcat无法启动,有这么几个原因?(1)代码有问题; (2)tomcat有问题; (3)端口被占; (4)动态web项目为3.0: (5)java环境运行内存不足; 这是比较常见的问题.解 ...
- 解密蓝牙mesh系列
解密蓝牙mesh系列 https://mp.weixin.qq.com/s/KdVhkgcmHIboA0xPFqFCgQ 1.NRF52832 & NRF52840 BLE mesh 协议栈 ...
- 并发编程(三)------并发类容器Copy-On-Write容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.JDK里的COW容器有两种: CopyOnWriteArrayList CopyOnWriteArraySet CopyOnWri ...
- Oracle 日志挖掘(LogMiner)使用
Logminer依赖于2个包:DBMS_LOGMNR和DBMS_LOGMNR_D,Oracle 11g默认已安装 Logminer 基本使用步骤 <1>. Specify a LogMin ...
- zabbix3.0通过yum安装笔记
zabbix3.0通过yum安装笔记 一.通过yum安装zabbix rpm -Uvh https://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix- ...
- MySQL5.7.24安装笔记
一.下载mysql-5.7.24 wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.24-el7-x86_64.tar.gz 二 ...
- CentOS6安装各种大数据软件 第七章:Flume安装与配置
相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...
- es6之扩展运算符 三个点(...)
对象的扩展运算符理解对象的扩展运算符其实很简单,只要记住一句话就可以: 对象中的扩展运算符(...)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中 let bar = { a: 1, b: 2 ...