Linux学习第12天:基于API函数的字符设备驱动开发:一字一符总见情

本节学习的内容主要为基于LinuxAPI函数的字符设备驱动的开发,还包括在驱动模块加载的时候如何自动创建设备节点。总结的脑图如下:

一、驱动原理

1.分配和释放设备号

申请设备号函数:

cpp 复制代码
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

注册设备号函数:

cpp 复制代码
int reister_chrdev_region(dev_t from, unsigned count, const char *name)//rrom起始设备号 count数量 name设备名

设备释放函数:

cpp 复制代码
void unregister_chrdev_region(dev_t from, unsigned count)

设备号分配实例:

cpp 复制代码
1 int major; /* 主设备号 */
2 int minor; /* 次设备号 */
3 dev_t devid; /* 设备号 */
4 5
if (major) { /* 定义了主设备号 */
6 devid = MKDEV(major, 0); /* 大部分驱动次设备号都选择 0 */
7 register_chrdev_region(devid, 1, "test");
8 } else { /* 没有定义设备号 */
9 alloc_chrdev_region(&devid, 0, 1, "test"); /* 申请设备号 */
10 major = MAJOR(devid); /* 获取分配号的主设备号 */
11 minor = MINOR(devid); /* 获取分配号的次设备号 */
12 }

大部分次设备号都选择0

2.注册方法

1)、字符设备结构

cdev结构体在/include/linux/cdev.h中定义如下:

cpp 复制代码
1 struct cdev {
2 struct kobject kobj;
3 struct module *owner;
4 const struct file_operations *ops;//file_operations
5 struct list_head list;
6 dev_t dev;//cdev
7 unsigned int count;
8 };

编写字符设备驱动之前,需要定义一个cdev结构体变量,这个变量就表示一个字符设备。

cpp 复制代码
struct cdev test_cdev;

2)、cdev_init

初始化函数cdev_init内容如下:

cpp 复制代码
void cdev_init(struct cdev *cdev, const struct file_operations *fops)

使用cdev_init函数初始化cdev变量代码如下:

cpp 复制代码
1 struct cdev testcdev;
2 
3
/* 设备操作函数 */
4 static struct file_operations test_fops = {
5 .owner = THIS_MODULE,
6 /* 其他具体的初始项 */
7 };
8 
9
testcdev.owner = THIS_MODULE;
10 cdev_init(&testcdev, &test_fops); /* 初始化 cdev 结构体变量 */

3)、cdev_add

cdev_add函数原型:

cpp 复制代码
int cdev_add(struct cdev *p, dev_t dev, unsigned count)

注册字符设备代码段内容:

cpp 复制代码
1 struct cdev testcdev;
2 
3
/* 设备操作函数 */
4 static struct file_operations test_fops = {
5 .owner = THIS_MODULE,
6 /* 其他具体的初始项 */
7 };
8 
9testcdev.owner = THIS_MODULE;
10 cdev_init(&testcdev, &test_fops); /* 初始化 cdev 结构体变量 */
11 cdev_add(&testcdev, devid, 1); /* 添加字符设备 */

4)、cdev_del

cdev_del原型内容:

cpp 复制代码
void cdev(struct cdev *p)

二、自动创建设备节点

自动创建设备节点以后,使用modprobe加载驱动模块成功的话就会自动在/dev目录下创建对应的设备文件。

1.modev机制

udev程序实现设备文件的创建与删除。

2.创建和删除类

class_create是类创建函数,class_create是个宏定义,内容如下:

cpp 复制代码
1 #define class_create(owner, name) \//owner一般为THIS_MODULE name为类名字 返回值是指向结构体class的指针,也就是创建的类
2 ({ \
3 static struct lock_class_key __key; \
4 __class_create(owner, name, &__key); \
5 })
6 
7
struct class *__class_create(struct module *owner, const char *name,
8 struct lock_class_key *key)

卸载驱动函数的时候需要删除类,class_destroy函数原型如下:

cpp 复制代码
void class_destroy(struct class *cls)//cls就是要删除的类

3.创建设备

创建好类以后,还需要在类下面创建一个设备,才能实现自动创建设备节点。

device_create函数原型如下:

cpp 复制代码
struct device *device_create(struct class *class,//clasd  要创建的类
struct device *parent,//parent 父设备 一般为NULL
dev_t devt,//devt 设备号
void *drvdata,//drvdata 设备可能会使用的一些数据 一般为NULL
const char *fmt, ...)//fmt 设备名字 生成/dev/xxx

卸载时,需要删掉创建的设备。device_destroy函数原型如下:

cpp 复制代码
void device_destroy(struct class *class, dev_t devt)//class 删除的类 devt删除的设备号

三、设置文件私有数据

编写open函数的时候将设备结构体作为私有数据添加到设备文件中,如下:

cpp 复制代码
/* 设备结构体 */
1 struct test_dev{
2 dev_t devid; /* 设备号 */
3 struct cdev cdev; /* cdev */
4 struct class *class; /* 类 */
5 struct device *device; /* 设备 */
6 int major; /* 主设备号 */
7 int minor; /* 次设备号 */
8 };
9
10 struct test_dev testdev;
11
12 /* open 函数 */
13 static int test_open(struct inode *inode, struct file *filp)
14 {
15 filp->private_data = &testdev; /* 设置私有数据 */
16 return 0;
17 }

在open函数里面设置好私有数据以后,在write、read、close等函数中直接读取private_data即可得到设备结构体。

本节学习的内容看似就几个函数而已,但是要将其替换改动到原来的驱动函数中还是需要一定的代码功力的。切记戒骄戒躁,放平心态,一遍一遍不厌其烦的去调试,去总结。相信功夫不负有心人,铁棒总能磨成针......


Linux版本号4.1.15 芯片MX6ULL

本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

相关推荐
菜鸟康35 分钟前
Linux系统编程——线程
linux·运维·服务器
两水先木示1 小时前
【Unity3D】ECS入门学习(八)块组件 ArchetypeChunk
学习·unity·ecs
worthsen1 小时前
Linux 服务管理 service systemd systemctl
linux·运维
Xiezequan2 小时前
C语言实现跨主机通讯
linux
szpc16212 小时前
100V宽压输入反激隔离电源,适用于N道沟MOSFET或GaN或5V栅极驱动器,无需光耦合
c语言·开发语言·人工智能·单片机·嵌入式硬件·生成对抗网络·fpga开发
巴拉特好队友2 小时前
找到一个linux静态库动态库的好资料.3
linux·运维·服务器
知初~3 小时前
java相关学习文档或网站整理
java·开发语言·学习
我走过的路你也许在走3 小时前
python装饰器学习案例
开发语言·python·学习
Hacker_Fuchen3 小时前
linux 中 Vi 和 Vim 的使用
linux·运维·vim
努力的小T3 小时前
Debian操作系统相对于Ubuntu有什么优势吗?
linux·运维·服务器·ubuntu·centos·云计算·debian