标签:
Android深度探索(卷1)HAL与驱动开发学习笔记(6)
第六章 第一个Linux驱动程序 统计单词个数
Linux系统将每一个驱动都映射成一个文件.这些文件称为设备文件或驱动文件,都保存在/dev目录中。这种设计理念使得与Linux驱动进行交互就像与普通文件进行交互一样容易。虽然C语言里没有事件的概念,但却有与事件类似的概念,这就是回调(c a l l b a c k)函数。因此,编写Lin u x驱动最重要的一步就是编写阴调函数,否则与设备文件交互的数据将无法得到处理。
6.1编写Linux驱动的步骤
* 上面8步中的前5步是关于如何编写Lin u x驱动程J字的,通过后3步可以使L i n u x驱动正常工作。
6.2 编写L i n u驱动程序前的准备工作
本例的L i n u x驱动源代码并未与li n u x内核源代码放在一起,而是单独放在一个目录。* 首先使用下面的命令建立存放Li n u x驱动程序的目录。
# mkdir -p/root/drivers/ch06/word_count
# cd /root/drivers/ch0 6/word_count
* 然后,使用下面的命令建立驱动源代码文件(word count.c)
# echo ’’>word_count.c
最后编写一个M a k e f i l e文件,
# echo ‘obj-m := word_count.o ’ > Makefile
6.3 编写L i n u x驱动程序的骨架(初始化和退出驱动)
代码中使用了p r i n t k函数。该函数用于输出日志信息printk函数与p r i n t f函数的用法类似。linux系统将内存分为了用户空间和内核空间,这两个空间的程序不能直接访问。p r i n t f函数运行在用户空间,p r i n t k函数运行在核空间。因此,属于内核程序的L i n u x驱动是不能直接访问p r i n t f函数的。运行在这两块内存中的程序之间交互的-方法很多。其中,设备文件就是一种主要的交互方式,如果用户空间的程序要访问内核空间,只要做一个可以访问内核空间的驱动程序,然后用户空间的程序通过设备文件与驱动程序进行交互即可.那么,如何在linux驱动程序中动态分配内存空间呢?解决类似的问题也很简单。既然L i n u x驱动无法直接调用运行在用户空间的函数,那么,在L i n u x内核中就必须要提供替代品。可以进入<Li n u x内核源代码>/i n c l u d e目录,该目录的各个子目录中…包含了大量的C语言头文件,这些头文件中定义资源就是运行在用户空间的程序的替代品。
6.4. 安装查看和卸载Linux驱动
* 安装Linux驱动
# ismod word_count.ko
* 查看word_count 是否安装成功
# lsmod I grep word_count
* 卸载Linux驱动
# remmod word_count
* 查看Linux驱动的输出信息
# dmesg | grep word_cound | tail -n 2
6.5 指定与驱动相关的信息
一般需要为L i n u x驱动程序,指定如下信息。
模块作者:使用MODULE_AUTHOR宏指定。
模块描述:使用MODULE_DESCRIPTION宏指定。
模块别名:使用MODULE_ALIAS宏指定。
开源协议:使用MODULE_LICENSE宏指定。
代码如下(一般放在word_count.c最后):
MODULE_AUTHOR(“lining”);
MODULE_DESCRIPTION(“statistics of word count .”);
MODULE_ALIAS(“word count module .”);
MODULE_LICENSE(“GPL”);
6.6 注册和注销设备文件
为w o r d_c o u n t驱动建立一个设备文件,该设备文件的名称是w o r d c o unt,位于/d e v目录中。设备文件与普通文件不同,不能使用I O函数建立,需要使用m i s c_r egister函数建立设备文件,使用m i s c_d e r e g i s t e r函数注销(移除〉设备文件。
* 编写中的注意事项
1.设备文件由主设备号和次设备号描述。而使用m i s c _ r e g i s t e r函数只能设置次设备号。主设备号统一设为10。主设备号为1 0的设备是L i n µ x系统中拥有共同特性的简单字符设备。这类设备称为m i s c设备。
2. miscdevice.name变量的值就是设备文件的名称。在本例中设备文件名称为w o r d c o u n t .
3. 如果成功注册了设备文件,m i s c _ _ r e g i s t e r函数返回非0的整数,如果注册设备文件失败返回0。
4. w o r d_c o u n t . c中的所有函数、变量都声明成了s t a t i c。C语言中用s t a t i c声明函数、变量等资源,系统会将这些函数和变量单独放在内存的某一个区域,直到程序完全退出,否则这些资源不会被释放, L i n u x驱动一旦装载,除非手动卸载或关机,驱动会一直驻留内存,因此这些函数和变量资源会一直在内存中。也就是说多次调用这些资源不用再进行压栈,出栈操作了,有利于提高驱动的运行效率。
6.7 指定回调函数
6.8测试Linux驱动的多种方法
1.使用Ubuntu Linux测试Linux驱动
2.A n d r o i d模拟器上通过原生(Native )C程序测试L i n u x驱动
* 用于Andr o i d模拟的g o l d f i s h内核默认不允许动态装载L i n u x驱动模块,因此需要在编译L i n u x内核之前执行如下命令配置L i n u x内核。
# cd kernel goldfish
# make menuconfig
* 执行上面的命令后,按空格键将第二顶“Enable loadable module s u p p ort”选中前面是(*),然后按回车键选入子菜单,选中前3项,否则L i n u x驱动模快仍然无法安装和卸载。当退出设置菜单时保持设置。最后重新编译Linux内核,成功编译内核后, A n d r o i d模拟器可以使用新生成的zImage内核文件动态装载L i n u x驱动模块。
*在执行build.h脚本文件完成对w o r ld_c o u n t驱动的编译、上传和安装的工作,然后进入A n d r o i d模拟器的终端,使用e c h o和d mesg命令可以演出w o r d _ c o u n t驱动和查看测试时结果。
* 为了使编译步骤尽可能简单使用Android设 置 编 译 参 数 , 并 使 用 make命令进行编译。首先在root/driver/ch06/word_count目录中建立一个A n d r o i d . m k文件,并输入如下的内容。
LOCAL PATH:= $ (call my -dir)
include $(CLEAR VARS)
#指定要编译的源代码文件
LOCAL _SRC _FILES := test _word_count .c
#指定模块名,也是编译后生成的可执行文件名
LOCAL_MODULE:= test_word_cunt
LOCAL _MODU LE _T AGS:= optional
include $(BUILD_EXECUTABLE)
A r i dro i d . m k文件中有如下两个地方需要说明一下.
LO C AL _MODULE_TAGS.
表示当前工程(A n d roi d .mk文件所在的目录)在什么模式下编译。如果设为optional,表示不考虑模式,也就是说,在任何膜式下都会编译。该变量可以设置的值有us er、use r d e b u g、e ng、 o p t i o n a l其中eng是默认值。
include $(BUILD_EXEC UT ABLE) .
BUILD _EXECUTABLE表示建立可执行的文件。可执行文件路径是<A n d r o i d源代码目录〉
3.使用Android ADK设置Linux驱动
4.使用JAVA代码直接操作设备文件来测试Linux驱动
5.使用S3C6410开发板测试Linux驱动
6.将驱动编译进Linux内核进行测试
Android深度探索(卷1)HAL与驱动开发学习笔记(6)
标签:
原文地址:http://www.cnblogs.com/zhangnene/p/5560635.html