1、驱动的价值就在于实现API
2、驱动是内核的一部分
3、驱动开发的步骤
1)驱动源码的编写、Makefile编写、编译
2)insmod装载模块、用应用程序测试、rmmod卸载模块
4、在linux中用find来查找某个文件所在的路径
find . -name ‘x210ii_qt_defconfig’ //在当前文件夹下面查找x210ii_qt_defconfig的路径
一般的xxx_defconfig文件在arch/arm/config/文件夹下
5、常用的模块操作指令
lsmod 将当前内核中已经安装的模块打印出来
insmod 向当前内核中去安装一个模块,用法是insmod xxx.ko
modinfo 打印出一个模块的自带信息,用法是modinfo xxx.ko
rmmod 从当前内核中卸载一个模块,用法是rmmod xxx(注意,不能加.ko)
6、__init(下载模块使用)是函数的修饰符,本质上是一个宏定义,在内核源代码中就有#define __init xxx。这个__init的作用就是
将被他修饰的函数放入到.init.text段中去(本来默认情况下函数是被放到.text段中)。整个内核中的所有的这类
函数都会被链接器放入到.init.text段中,所以所有的内核模块的__init修饰的函数其实是被统一放在一起的。内核
启动时统一加载.init.text段中的这些模块安装函数,加载完后就会把这个段给释放掉以节省内存。
__exit(卸载模块使用),原理和__init相似。
7、驱动源代码中包含的头文件是内核源码目录下的include目录下的头文件。
8、要保证模块的vermagic(版本信息)和内核的vermagic的一致,否则模块不能挂接到内核中去。
如何保证两者相等呢:需要编译模块的内核就是将来我们要挂载的内核。
9、file_operations结构体(里面的元素都是函数指针)的作用就是,做API和驱动之间的桥梁。
API中的:open、read、write、close等函数接口,其函数的实体在驱动源码中。file_operations结构体
就是充当实体和接口之间的连接桥梁。
每个驱动设备都需要一个该结构体类型的变量。
在使用file_operations结构体的时候一定要包含头文件<linux/fs.h>
10、register_chrdev是内核开发者所编写的注册函数。
11、驱动通过register_chrdev函数向内核注册自己的file_operations结构体。
register_chrdev函数的详解:
函数体:
static inline int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
{
return __register_chrdev(major, 0, 256, name, fops);
}
参数解析:
static 用来防止和其它文件冲突
inline 用来提高效率
major 主设备号,传0进去表示让内核给我们自动分配一个设备号(也可以自己指定)
name 设备的名字
fops 把我们自己的file_operations结构体的变量,通过指针传给这个函数,然后这个函数向内核注册这个驱动。
256 的意思是最多装载256个设备
成功返回0,失败返回一个负整数
12、unregister_chrdev函数与上面的注册函数相对应,用来卸载。
原型:
static inline void unregister_chrdev(unsigned int major, const char *name)