字符设备驱动05 | 学习笔记

简介: 快速学习字符设备驱动05

开发者学堂课程【物联网开发 - 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)

进行查看主设备号

相关文章
|
9月前
|
安全 网络协议 Linux
Linux驱动开发 设备驱动的基本概念
Linux驱动开发 设备驱动的基本概念
|
4月前
|
Linux API
字符设备驱动(1):Linux字符设备驱动结构
字符设备驱动(1):Linux字符设备驱动结构
43 1
|
7月前
|
存储 Linux API
嵌入式Linux 字符设备驱动标准ioctl接口
嵌入式Linux 字符设备驱动标准ioctl接口
|
8月前
|
存储 安全 Unix
【Linux驱动】字符设备驱动
【Linux驱动】字符设备驱动
38 0
|
8月前
|
算法 Linux C语言
Linux驱动中常用的一些接口函数
Linux驱动中常用的一些接口函数
|
9月前
|
存储 Linux 文件存储
Linux驱动入门(6.1)LED驱动---设备树
Linux驱动入门(6.1)LED驱动---设备树
91 0
|
10月前
|
Linux 编译器
Linux设备驱动---字符设备驱动接口函数
Linux设备驱动---字符设备驱动接口函数
93 1
|
10月前
|
存储 缓存 Unix
Linux设备驱动程序(三)——字符驱动
本章的目的是编写一个完整的字符设备驱动,我们开发一个字符驱动是因为这一类适合大部分简单硬件设备,字符驱动也比块驱动易于理解。
188 0
|
Linux API
字符设备驱动基础知识
字符设备驱动基础知识
|
Linux 芯片
Linux驱动之I2C设备驱动
下面的代码分析主要都在注释中,会按照驱动中函数的执行顺序分析。