Android深度探索(卷1)HAL与驱动开发学习笔记(6)

Android深度探索(1)HAL与驱动开发学习笔记(6linux

第六章 第一个Linux驱动程序 统计单词个数函数

 

Linux系统将每个驱动都映射成一个文件.这些文件称为设备文件或驱动文件,都保存在/dev目录中。这种设计理念使得与Linux驱动进行交互就像与普通文件进行交互同样容易。虽然C语言里没有事件的概念,但却有与事件相似的概念,这就是回调(c a l l b a c k)函数。所以,编写Lin u x驱动最重要的一步就是编写阴调函数,不然与设备文件交互的数据将没法获得处理。学习

6.1编写Linux驱动的步骤测试

  1. 创建Linux驱动骨架
  2. 注册和注销设备文件
  3. 指定与驱动相关的信息
  4. 指定回调函数
  5. 编写业务逻辑
  6. 编写makefile 文件
  7. 编译Linux驱动程序
  8. 安装和卸载Linux驱动

* 上面8步中的前5步是关于如何编写Lin u x驱动程J字的,经过后3步可使L i n u x驱动正常工做。ui

 

6.2 编写L i n u驱动程序前的准备工做spa

本例的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 cC语言中用s t a t i c声明函数、变量等资源,系统会将这些函数和变量单独放在内存的某一个区域,直到程序彻底退出,不然这些资源不会被释放, L i n u x驱动一旦装载,除非手动卸载或关机,驱动会一直驻留内存,所以这些函数和变量资源会一直在内存中。也就是说屡次调用这些资源不用再进行压栈,出栈操做了,有利于提升驱动的运行效率。

 

6.7 指定回调函数

  1. w o r d _ c o u n t_r e a dword_c o u n t_w r i t e函数的参数基本相同,只有第2个参数b u f稍微有差别。word _count _r e a d.函数的b u f参数类型是c h a r*,而w o r d _count _w r i t e函数的b u f参数类型是co n s t  char*;这就意味着w o r d _count _w r i t e函数中的b u f参数值没法修改。Word_count_read函数中的b u f参数表示从设备文件读出的数据,也就是说b u f中的数据均可能自设备文件读出,至于能够读出多少数据,取决于w o r d _count _r e a d.函数的返回值。
  2. 因为内核空间的程序不能直接访问用户空间中的数据,所以须要在.w o r d_c o u n t -r e a dword _c o unt_w r i t e函数中分别使用copy_to_user和c o p y _ from_user函数将数据从内核空间复制到用户空间戒从用户空间复制到内核空间。

 

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 od 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 eruse 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内核进行测试

相关文章
相关标签/搜索