开发者学堂课程【物联网开发 - Linux驱动开发实操演练:字符设备驱动05】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/657/detail/10877
字符设备驱动05
内容介绍
一、课前知识回顾
二、字符设备驱动编写
一、课前知识回顾
所有的字符驱动都是基于内核模块完成的。
内核模块三要素:入口,出口函数,GPL 的声明
字符设备驱动的框架是围绕一个 cdv 结构体来进行的。
首先,第一步是申请 cdv 结构体,为 cdv 结构体申请一部分空间。
再进行初始化,完成后添加到内核。
在过程中需要一个设备号,结合上节分配设备号和申请注册设备号两种方法
将驱动注册到内核,执行初始化和添加到内核的动作。
将驱动从内核中卸载,应将申请到的资源释放掉,同时将字符设备驱动从内核中注销掉。
再卸载时,调用卸载函数或目标函数。
所以这些动作是在相应的位置去完成的
首先分配初始化与添加这些动作应该放在入口处去进行,加载时去执行。
二、字符设备驱动编写
1、第一步
实际上是为 cdv 去分配地址空间,此过程需要用到 cdv-t 类型的设备号。在使用 cdev-add 字符设备前,必须去分配一个设备号。
在一个位置去申请设备号存在两种方法:
(1)自动分配alloc -chrdev-region
(2)指定设备号注册register-chrdev-region
建议使用 alloc -chrdev-region,因为使用的设备号由内核来管理。
内核知道当前设备号是否使用,将未使用的设备号分配出来。一般情况下均可成功。若去注册,并不支出设备号是否使用,有可能失败。
因此建议使用 alloc -chrdev-region,
第一步:
//@alloc dev-t devno
alloc -chrdev-region(dev-t*,unsigned ,unsigned count char*)
根据自动补全函数的类型去传递时长
根据已知的alloc -chrdev-region的功能参数返回值
第一个是传入 dev-t 数据类型的指针,目的获取设备号以后,保存地址。
因此使用前,定义一个 dev-t 类型的设备号 Dev-t devno。
传入 dev-t* 时,传入地址,可以将 alloc dev-t devno 可作为主设备号。
第二个
unsigned baseminor
次设备号的起始
进行宏定义
#define BASEMINOR 0
#define COUNT 3
#define NAME “chrdev-demo”
进行参数传递
alloc -chrdev-region(devno BASEMINNOR COUNT NAME )
接下来,由于存在失败的可能,进行返回值。
定义一个变量来接受返回值
Int ret
Ret =alloc -chrdev-region(devno BASEMINNOR COUNT NAME )
If(ret<0){
Printk(KERN-ERR“alloc -chrdev-region failed...\n”);
Retun ret;
}
2、第二步
//1.alloc cdev
分配 cdev 结构体
运用函数 Cdev-alloc()
对于该函数,是没有参数的,
存在返回值,返回值为结构体指针
定义结构体指针变量接收返回值
Cdevp
对于 Cdev-alloc 返回结构体,若失败返回为空,
因此进行判断
If(NULL==cdevp {
Retun=ENOMEM;
}
失败最大可能为内存不够,添加提示语句
If(NULL==cdevp)
{
Prink(kern-err:cdev-alloc failled...\N”);
Retun=ENOMEM;
}
当编写至此时,存在问题
比如说,申请失败后退出,并未释放前面申请的资源
在申请 cdv 结构体失败后,释放掉资源
使用 goto 语句完成处理
Goto err1
跳转到 return 后面
Err1:
Return ret
此时
Ret=-ENOMEN
Goto err2
跳转完成后,释放掉申请的设备号资源
使用 unregister-chrdev-region 函数(devno count)
//2.cdev init
第二步进行初始化
使用函数 cdev-init
返回值为空
需要自己定义一个操作方法级
Fops={
进行初始化,是因为操作方法级是提供应用接口
是对应用设备的接口
对具体设备的控制
因为为初始化完成的内容操作方法级存在很多成员变量,所以当我们使用时便针对使用变量进行初始化。
必须要用到
Open
Release
针对这两个最基本接口进行初始化
Open =‘
Release =’
这种方法叫结构体的部分初始化
此外对 Owner 进行赋值
Owner=THIS-MOOULE
Open =‘
Release =’
根据函数的数据类型进行定义
Demo-open(struct inode *inode struct file *flip)
{
Return 0;
}
之后加调制语句,如果执行,进行打印
Demo-release (truct inode *inode struct file *flip)
{
Return 0;
}
之后加调制语句,如果执行,进行打印
3、第三步:添加内核管理
//3.cdev add
调用 cdev-add(cdevp,DEVNO, COUNT)函数
返回值代表
如果失败返回错误代码
错误判断
If(ret<0){
Prink(kern-err:cdev-alloc failled...\N”);
}
完成后,进行 goto 跳转释放申请资源
假设只申请设备号资源
跳转到
Err2 进行资源释放
在退出时进行释放资源
Cdev-del (cdevp)
unregister-chrdev-region(devno count)
当设备号申请成功以后
Printk(KERN-INFO “major”=%d\N”MAJOR
(devNo)
进行查看主设备号