linux内核模块编程(四)----字符设备驱动开发几个关键函数分析

先给自己打个广告,本人的微信公众号正式上线了,搜索:张笑生的地盘,主要关注嵌入式软件开发,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题
在这里插入图片描述

一 why

前一篇博客《linux内核模块编程(三)----字符驱动设备开发》,我们初步实现了一个linux内核字符设备驱动,主要是为了大家参照该驱动程序源码,学会如何进行字符设备驱动开发,不知道大家是否成功在自己的本地运行起来这个驱动。
今天这篇文章,我们来谈谈字符设备驱动开发的框架套路,几个重要的概念和重要内核函数。

二 what

  1. 字符设备驱动框架
    首先我们看一下字符设备驱动的软件框架,如下。字符设备驱动运行在kernel space,用户空间通过常规的open,write,read函数调用驱动中对应的xxx_open,xxx_write,xxx_read函数以实现对某个硬件设备的控制
    在这里插入图片描述
1. 必须要有一个设备号,用于在众多设备驱动中进行区分
2. 用户必须知道设备驱动对应的设备节点(设备文件名)
3. 在linux中一切皆文件,因此对设备的操作被linux封装成了文件操作,应用空间的open,wrie,read的时候,实际在内核驱动代码中有对应的xx_open,xx_read,xx_write
  1. 字符设备驱动相关的内核函数
    2.1 申请设备号
// 创建设备号
int register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
参数1:主设备号
	设备号(32bit dev_t) = 主设备号(12bit) + 次设备号(20bit)
		主设备号 : 表示一类设备 --- 比如:手机上camera
		次设备号 : 表示一类设备中的某一个:前置camera,后置camera
		
		给定的方式有两种:
			1. 动态--参数1直接填0
			2. 静态--指定的一个整数,250
参数2:描述设备信息,可以自定义
	/proc/devices 列举出所有的已经注册的设备
参数3:文件操作对象 --- 提供open,wrie,read
返回值:正确返回0,错误返回负数

有创建就有注销

static inline void unregister_chrdev(unsigned int major, const char *name)

2.2 创建设备节点
创建设备节点的时候,可以选择手动创建,也可以选择自动创建。手动创建一般适合在debug的情况,在一般的驱动中建议采用自动创建设备节点的方式

1. 手动创建---缺点: /dev/目录中文件都是在内存中,断电后 /dev/目录中文件都会消失
	mknod /dev/设备名 类型 主设备号 次设备号
	比如: 
		mknod /dev/char0 c 240 0

2. 自动创建(通过 udev/mdev机制)
	class_create
		#define class_create(owner, name)		\
		({						\
			static struct lock_class_key __key;	\
			__class_create(owner, name, &__key);	\
		})
			struct class *__class_create(struct module *owner, const char *name,
		     struct lock_class_key *key)
		参数1: THIS_MODULE
		参数2:字符串名字,自定义
		返回一个struct class指针


	struct device *device_create(struct class *class, struct device *parent,
		     dev_t devt, void *drvdata, const char *fmt, ...)
		参数1: class_create返回的struct class指针
		参数2:表示父亲,一般直接填 NULL
		参数3:表示设备号类型, MKDEV(major, 0)
		参数4:表示私有数据,一般也是直接填NULL
		参数56:可变参数,字符串,表示设备节点的名字
		返回一个struct device指针
  1. 总结
    字符设备驱动开发的一般步骤如下,再次强调一下是在linux内核4.15版本下的总结,可能有些函数接口不一样
初始化注册步骤
1. 申请字符设备的资源---申请设备号,通过register_chrdev()函数实现
2. 创建设备节点,通过class_create()device_create()两个函数实现

当我们卸载某个字符设备驱动时,对应的注销和注册是成对出现的,但是记住遵循一个原则,先注册的后注销,后注册的先注销,步骤如下
1. 先调用device_destroy()---对应函数device_create()
2. 再调用class_destroy()---对应函数class_create()
3. 最后调用unregister_chrdev()---对应函数register_chrdev()

关于一个完整的字符设备驱动程序示例,还请参考《linux内核模块编程(三)----字符驱动设备开发》,该博客中有示例源码。后期有可能还是会参照这样的思路来写博文,先给出一个示例程序,编译运行,然后再出一篇博文分析它,或者有可能在一片博文中先给出示例,然后再分析,这样可能会造成一篇博文较长,不知道大家是否能看完。

三 to be continued

因为字符设备驱动的目的,是方便用户空间程序能够驱动硬件设备工作的,所以下一篇博文会给出如何在用户空间通过调用字符设备驱动,来控制我们的硬件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章