一、Linux系统将每个驱动都映射成一个文件。这些文件称为设备文件或驱动文件,都保存在/dev目录中。这使得与Linux驱动进行交互就向与普通文件进行交互一样容易。大多数Linux驱动都有与其对应的设备文件,因此与Linux驱动交换数据变成与驱动设备交换数据。
二、编写Linux驱动程序
1.建立Linux驱动骨架
Linux内核在使用驱动时需要装载与卸载驱动
装载驱动:建立设备文件、分配内存地址空间等;module_init 函数处理驱动初始化
卸载驱动:删除设备文件、释放内存地址空间等;module_exit函数处理退出
包含这两个函数的两个宏的C程序文件也可看做是Linux驱动的骨架
2.注册和注销设备文件
任何一个Linux驱动都需要有一个设备文件,否则应用程序将无法与驱动程序交互。
建立设备文件:在第一步编写的处理Linux初始化工作的函数中完成。misc_register函数
删除设备文件:在第一步编写的处理Linux退出工作的函数中完成。misc_deregister函数
3.指定与驱动相关的信息
驱动程序是自描述的,驱动程序的作者姓名、使用的开源协议、别名、驱动描述等信息。这些信息都需要在驱动源代码中指定。
MODULE_AUTHOR、MODULE_LICENSE、MODULE_ALLS、MODULE_DESCRIPION等宏可以指定与驱动相关的信息
4.指定回调函数
一个驱动程序并不一定要指定所有的回调函数,回调函数会通过相关机制进行注册
5.编写业务逻辑
具体的业务逻辑与驱动的功能有关,业务逻辑可能由多个函数、多个文件甚至是多个Linux驱动模块组成
6.编写Makefile文件
Linux内核源代码的编译规则是通过Makefile文件定义的。因此编写一个新的Linux驱动程序必须有一个Makefile文件
7.编译Linux驱动程序
可以直接编译进内核,也可以作为模块单独编译
8.安装和卸载Linux驱动
若将Linux驱动编译进内核,只要Linux使用该内核,驱动程序就会自动转载
若Linux驱动程序以模块单独存在,需使用insmod或modprode命令装载Linux驱动模块,rmmod命令卸载Linux驱动模块
三、统计单词个数
利用设备文件作为介质与应用程序进行交互,应用程序通过向设备文件传递一个由空格分隔的字符串,然后从设备文件读出来的是该字符串包含的单词数。
准备工作:
1.建立存放Linux驱动程序的目录:
“mkdir -p /root/drivers/ch06/word_count”
“cd /root/drivers/ch06/word_count”
2.建立驱动源代码文件:“echo ‘ ’ > word_count.c”
3.编写Makefile文件:“echo ‘obj-m := word_count.o’ > Makefile”
obj-m表示将Linux驱动作为模块(.ko文件)编译,obj-y表示将Linux驱动编译进Linux内核。两者都需使用“:=”赋值。使用obj-y,.o文件会被连接进built-in.o文件连 接进内核。built-in.o文件是连接同一类程序的.o文件生成的中间目标文件。“make menuconfig”可配置每一个驱动及其他内核程序是否允许编译进内核。当驱动依赖其他程 序时,依赖文件要使用module-y或module-objs指定(module表示模块名)。
编写骨架
骨架部分主要是Linux驱动的初始化和退出函数。
printk函数用于输出日志信息。printf 函数运行在用户空间,printk函数运行在内核空间,属于内核程序的Linux驱动不能直接访问printf函数。使用dmesg命令查看由 Linux驱动输出的日志信息。
指定与驱动相关信息
modinfo命令查看信息,depends表示当前驱动模块的依赖,vermagic表示当前Linux驱动模块在哪个Linux内核版本下编译。
模块作者:MODULE_AUTHOR
模块描述:MODULE_DESCRIPTION
模块别名:MODULE_ALIAS
开源协议:MODULE_LICENSE(GPL协议、LGPL协议、BSD协议、Apache Licence 2.0协议、MIT协议)
注册和注销设备文件
设备文件需要一个结构体(miscdevice)来描述与其相关的信息,其成员变量fops用于描述设备文件在各种可触发事件的函数指针,其数据类型也是一个结构体 file_operations。使用misc_register函数只能设置次设备号。主设备号为10的设备是Linux系统中拥有共同特性的简单字符设备,称为misc设备。
“cat /proc/devices”命令可显示当前系统中有哪些主设备以及主设备号。
指定回调函数并实现统计单词数的算法
用户空间的应用程序与内核空间的驱动程序交互最长用的方式是读写设备文件,通过file_operations.read和file_operations.write成员变量可以分别指定读写设备文件 要调用的回调函数指针。
编译、安装、卸载Linux驱动程序
insmod和modprobe的区别是modprobe命令可以检查驱动模块的依赖性。使用modprobe命令装载驱动模块之前需先使用depmod命令检测Linux驱动模块的依赖关 系。depmod命令必须使用Linux驱动模块(.ko文件)的绝对路径,其会将内核模块的依赖信息写入当前正在使用的内核的modules.dep文件。Modprobe命令只需使用驱 动名称,不需要跟.ko。
四 、在eclipse中开发Linux驱动程序
第一步:建立C工程
第二步:建立C源代码文件链接 New>Source Folder Folder name 输入 src,导入word_count.c文件
第三步:设置include路径 单击菜单项properties,C/C++General > Paths and Symbols ,选中Include的GNU C项,Add添加两个路 径:/root/kernel/goldfish/include和/root/kernel/goldfish/arch/arm/include
第四步:编译Linux驱动
五、测试Linux驱动
第一步:导入test_word_count.c文件
第二步:设置include路径
第三步:建立Target Make Target > Create ,在Target name 文本框中输入word_count_eclipse_test,点击OK
第四步:Build工程 Make Target > Build,选中第三步中建立的文件,然后点击Build
第五步:运行测试程序 Run As > Local C/C++ Application