目录
系统整体工作原理:
应用层->API->设备驱动->硬件
应用层调用API:open、read、write、close等
驱动源码中提供真正的open、read、write、close等函数实体去操控硬件
file_operations结构体
在fs.h文件中
(1)元素主要是函数指针,用来挂接实体函数地址
(2)每个设备驱动都需要一个该结构体类型的变量
(3)设备驱动向内核注册时提供该结构体类型的变量(注册函数是从内核来的register_chrdev)
具体了解注册函数可看:一文搞懂内核中cdev的各种注册函数
register_chrdev()
需要包含#include <linux/fs.h> 如果注册成功,返回0,不成功则返回一个负数(整个Linux内核都是这么设计的)
major:分配的设备号(1-255),类似身份证号,和设备绑定,可以自己指定。
name:驱动的名字。(因为打印的是主设备号的话我们肯定看不懂,所以要打印设备的名字)
const struct file_operations *fops:传递file_operations结构体,向内核注册
这个函数的其他注意知识点:(值得我们去知道)
static:改变函数的链接属性,防止与其他文件的同名函数发生冲突
inline:
总所周知,函数是究极强烈不建议定义在头文件中的(如果这个函数同时被两个及以上的函数所使用,会出现多重定义的问题)。
所以内核用inline处理这个函数。当某个函数需要用这个函数时,这个函数会直接内联的展开。
当然,有人会问了,为什么不放在.c文件呢,放.c文件不就得了么。放,h文件得本质原因还是因为这个函数太短了,只有一句话(对于很短的函数,一般在内核里,一两句的函数一般用inline,减少调用资源,增加速度效率)
如何管理字符设备驱动
(1)内核中有一个数组用来存储注册的字符设备驱动(或者链表)
(2)register_chrdev内部将我们要注册的驱动的信息,存储在数组中相应的位置
(3)查看内核中已经注册过的字符设备驱动(和块设备驱动)
cat /proc/devices
这里浅讲一下/proc
是一个虚拟文件系统,并不是实际存在我们硬盘上的文件,而是一个内核用数据结构虚拟出来的一个文件,我们用cat读取它,只是读取内核的数据结构的值,
如上面的cat /proc/devices,我们只是读取内核管理这个设备驱动的数组的值。如果是空的地方就不管,有值的地方就把所存的属性打印出来。
详细可以参考:Linux系统proc详解