一、驱动分类
1)字符设备驱动:设备对数据的处理是按照字节流的形式进型的,在开发板或者电脑上我们的绝大多数设备都是字符设备。比如串口,lcd,led,iic,ketpid,鼠标等都是按字节处理数据的。
2)块设备驱动:设备随数据的处理是按照若干个块进行的。一个块又固定大小,比如512\1024…每次读写都是按块的倍数进行,一般用于存储设备:SD卡硬盘光盘等。
3)网络设备驱动:专门针对网络设备的一类驱动。
//注意:在入口申请了申明资源就要对应的在exit中释放申明资源,都有对应的。
二、字符设备驱动框架
1、驱动框架
1)头文件,包含文件,里面的调用的函数都是从头文件里面来的一般的linux/init.h linux/module.h …后期你在代码上用到什么函数你就得把头文件加上去。
2)驱动模块装在和卸载申明入口module_init(FUNCTION)module_exit(funtion)(,声明入口必须在申明后面,即在3的后面 要不然会报错)
3)实现驱动装载和卸载模块申明。把function函数实现
4)GPL申明/内核虽然开源,但你不能瞎搞,所以你用它的时候就相当于签了一个协议。
2、字符设备框架在驱动框架的基础上添加了以下框架。
字符设备驱动框架
1,必须有一个设备号,用在众多到设备驱动中进行区分
2,用户必须知道设备驱动对应到设备节点(设备文件)
linux把所有到设备都看成文件
crw-r----- 1 root root 13, 64 Mar 28 20:14 event0
crw-r----- 1 root root 13, 65 Mar 28 20:14 event1
crw-r----- 1 root root 13, 66 Mar 28 20:14 event2
3,对设备操作其实就是对文件操作,应用空间操作open,read,write的时候
实际在驱动代码有对应到open, read,write
1)申请设备号
int register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
参数1:主设备号
设备号(32bit–dev_t)==主设备号(12bit) + 次设备号(20bit)
主设备号:表示一类设备–camera 次设备号: 表示一类设备中某一个:前置,后置
给定到方式有两种:
1,动态–参数1直接填0 2,静态–指定一个整数,250
参数2: 描述一个设备信息,可以自定义
/proc/devices列举出所有到已经注册的设备
参数3: 文件操作对象–提供open, read,write
返回值: 正确返回0,错误返回负数
2)创建设备节点:为什么要创建设备节点?节点就是一个位于磁盘的文件(体现了Unix一切皆文件)这个节点下面接存储着(挂载)设备好等信息
创建设备节点需要用到俩个函数
(1):我们要用到一个类:类是c++里面的概念,类里面的成员只能由指定的对象来用。
class_create
:struct class *class_create(owner, name)//创建一个类
参数1: 一般THIS_MODULE
参数2: 字符串名字,自定义
返回一个class指针
(2)申请设备节点
struct device *device_create(struct class * class, struct device * parent, dev_t devt,
void * drvdata, const char * fmt,...)
参数1: class结构体,class_create调用之后到返回值
参数2:表示父亲,一般直接填NULL
参数3: 设备号类型 dev_t (填32位的设备号 12位主设号,20位次设备号)(可以用函数(MKDEV(MA,MI)))
参数4:私有数据,一般直接填NULL
参数5和6:表示可变参数,字符串,表示设备节点名字
我们创建了申明要从下往上释放申明,就跟malloc和free一样,后申请的先释放。
在模块卸载的实现里面释放。
这样我们的框架就搭好了
——————————————————————————————————————————
三、一些用法的实现
1、模块符号的参数传递
我们知道我们的模块装载实现后面参数必须是void类型,那么我们要传参数怎么办?
比如我要传递一个uart的波特率。
我们只需要在装载模块的时候insmod XXXX.ko的时候后面加上参数
并且申明参数和指定不传参的时候的默认参数就可以了。
参数处理:每一个参数都要处理,名称,类型,权限
2.默认参数
2、模块符号导出
我们模块不可能所有的实现函数都要写,比如我要调用另一个模块下的函数,那么我要怎么调用呢,这就需要
EG:模块2调用模块1中的符号(函数名属于符号)
1模块一需要用在函数后面加上:
EXPORT_SYMBOL(symbol);将符号导出,并且,由于模块2对模块一存在依赖‘
所以在装载的时候吗模块一要装载载在模块2前面
那么来个相互依赖的模块怎么办呢?
我们用modpord:这个命令在可以装载多个模块。
————————————————————————————————————————————
4)实现文件操控对象
我们知道一切皆文件,所以我们驱动也是利用文件来实习的,
我们利用文件操控对象,但是在2哪里我们写一个文件&my_fopen但是没有去实际写文件超控
我们添加以上就可以实现文件超控了。
全部代码