Linux系统将每一个驱动都映射成一个文件.这些文件称为设备文件或驱动文件,都保存在/dev目录中。编写linux驱动最重要的一步就是编写回调函数,否则与设备文件交互的数据无法得到处理。

1. 编写linux驱动程序的步骤:

第 1 步:建立 Linu x 驱动骨架 (装载和卸载 Linu x 驱动):

Linux 内核在使用驱动时首先需要装载驱动。当 Linux系统退出时需要卸载 Linux 驱动,在卸载的过程中需要释放由 linux 驱动占用的资源,例如,删除设备文件、释放内存地址空间等。在 Linux 驱动程序中需要提供两个函数来分别处理驱动初始化和退出的工作,这两个函数分别module_init和 module_exit宏指定。

第 2 步:注册和注销设备文件:

    建立设备文件的工作一般在第一步编写的处理linux初始化工作的函数中完成------misc_register创建设备文件;

   删除设备文件一般在第一步编写的处理linux退出工作的函数中完成-----misc_deregister删除设备文件。

第 3 步:指定与驱动相关的信息:

驱动程序都是自描述的。例如:modififo命令获取驱动的作者、姓名、使用的开源协议、别名、驱动描述等信息。通过

MODULE_AUTHOR\MODULE_LICENSE等完成。

第 4 步:指定回调函数

事件:linux包含的许多动作。例如:想设备文件写入数据名称称为写事件,linux系统会调用对应驱动程序的write回调函数,从设备文件读数据时会触发“读事件”,linux系统会调用对应的read函数。

回调函数通过相关机制进行注册,例如,与设备文件相关的回调函数会通过 misc_register 函数进行注册。

第 5 步:编写业务逻辑:

核心部分,具体的实现根据具体的情况决定。

第 6 步:编写 Makefile文件:

 Linu: 内核源代码的编译规则是通过 Makefi le 文件定义的。

第 7 步:编译 Linux 驱动程序

Linux 驱动程序,可以直接编译进内核,也可以作为模块单独编译。

第 8 步:安装和卸载 Linux 驱动:

1.如果将linux驱动编译进内核,只要linux使用内核驱动程序会自动装载。

2.如果linux驱动模块单独存在,需使用insomod或modprobe命令装载linux驱动模块,使用rmmod命令卸载模块。

 注意:区分insmod 和 modprobe命令:

modprobe可以检查驱动模块的依赖性。如 A 模块依赖子B 模块(装载A 之前必须先装载 B)。如果使用 insmod 命令装载A 模块,会出现错误。 而使用 modprobe 命令装载 A 模块, B 模块会现在装载。在使用 modprobe 命令装载驱动模块之前,需要先使用 depmod 命令检测 Linux 驱动模块的依赖关系。

2.学习第一个linux驱动:统计单词个数:利用设备文件作为介质与应用程序进行交互。

内容:应用程序通过向设备文件传递一个由空格分隔的字符串(每一个被空格隔开的子字符串称为一个单词),然后从设备文件读出来的是该字符串包含的单词数。

1>准备工作:

代码:1.建立存放linux驱动程序的目录:

Mkdir –p /root/drivers/ch06/word_count

Cd /root/drivers/ch06/word_count

        2.建立驱动源代码文件(.c)

         Ehco ‘’>word_count.c

       3.编写一个Makefile文件

   echo ’obj-m :=word_count.o’ > Makefile

其中 obj-m表示将 Linux 驱动作为模块(.ko 文件)编译。

如果使用 obj-y,则将 Linux 驱动编译 进 Linux 内核。

其中 built-in.o 文件是连接向一类程序的.o 文件生成的中间目标文件。该目标文件包含了所有可连接进 Linux 内核的字符驱动(通过 make menuconfig 命令可以配置每一个驱动及其他内核程序是否允许编译进内核)。

如果 Linux 驱动依赖其他程序,如 process.c、 data.c,需要按如下方式编写 Makefile 文件。

obj-m := word_count . 。

 word_count_y : = process.o data.o

其中依赖文件要使用 module_y 或 module_objs 指定。 module 表示模块名,如 word_count .

2>编写linux驱动程序的骨架:

Linux系统包括:用户空间【printf】和内核空间【printk】,且用户空间不可以直接访问内核空间。用户空间编写一个可以访问内核的驱动程序,用户空间通过访问设备文件从而访问驱动程序。

 那么,如何在linux 驱动程序中动态分配内存空间呢?解决类似的问题也很简单。既然 Linux 驱动无法直接调用运行在用户空间的函数,那么,在Linux 内核 中就必须要提供替代品。

使用下面的命令编译Linux驱动源代码。

 make -c /usr/src/linux-headers-3.0.0-15-generic  M=/ root/driver/ch06/word_count

 安装驱动: insmod xxxx.ko

 卸载驱动:rmmod xxxx

 查看驱动是否安装成功:lsmod |grep xxx

 查看由linux驱动输出的日志信息:

Dmesg | grep xxx|tail-n 2

Cat /usr/log/syslog|grep xxx |tail –n 2

3>指定与驱动相关的信息:

  1. 一般需要为 Linux 驱动程序,指定如下信息:

模块作者:使用 MODULE AUTHOR 宏指定。

 模块描述:使用 MODULE DESCRIPTION 宏指定。

模块别名:使用 MODULE ALIAS 宏指定。

开源协议z 使用 MODULE_LICENSE 宏指定。

      2.查看.ko文件信息使用:

 modinfo word_count.kc

      3.使用之前讲述的命令指定上述4种信息。

例如:MODULE_AUTHOR(“linging”);

      5.开源协议:GPL、LGPL、BSD协议、Apache license2.0协议、MIT协议。

这儿着重介绍GPL: 通用性公开许可证(General Public License,简称GPL)。GPL同其它的自由软件许可证一样,许可社会公众享有:运行、复制软件的自由,发行传播软件的自由,获得软件源码的自由,改进软件并将自己作出的改进版本向社会发行传播的自由。与其它不同之处:开源的更彻底、且具有传染性。

4>注册和注销设备文件:

   设备文件位于/dev目录下。设备文件与普通文件不同,不能使用 IO 函数建立,需要使用 misc_register 函数建立设备文件, 使用 misc_deregister 函数注销(移除〉设备文件。而且设备文件还需要一个结构体( miscdevice)来描述与其相关的信息。

注意:

1. 设备文件由主设备号和次设备号描述。而使用 misc_register函数只能设置次设备号。 主设备号统一设为10。主设备号为 10的设备是 Linux系统中拥有共同特性的简单字符设备。

2.  Fileoperations.owner=module结构:表示fileoperation被应用在这些有module指定的驱动模块

Fileoperations.owner=This.module表示只可以应用于当前模块

3.注册成功返回非0整数,注册失败,返回0

4.static:C 语言中用 static 声明函数、变量等资源,系统会将这些函数和变量单独放在内存的某一个区域,直到程序完全退出,否则这些资源不会被释放。

5.使用ls –l /dev查看主次设备号。

6.使用cat /proc/devices显示当前系统中有哪些主次设备号。

5>指定回调函数

通过 file_operations.read和 file_operations. write 成员变量可以分别指定读写设备文件要调用的回调函数指针。

6>实现统计单词个数的算法:

由空格、制表符、回车符和换行符分隔的字符串算做一个单词。

4.使用多种多种方式测试linux驱动:

1. 使用Ubuntu _linux测试 Linux 驱动:

2. 在 Android 模拟器上通过原生( Native ) C 程序测试 Linux 驱动

第一种方法:

1>查看是否可以将 word count.ko 安装在 Android 模拟器上?

答:执行 bui ldsh 脚本-à选择“Android模拟器”[脚本会自动将 word count.ko 文件上传到 Android模拟器的Ida饱/local 目录,并进行安装]。

2>注意:如果读者选择的是 S3C6410 开发板,在安装 word count.ko 时就会输出如下的错误信息:

insmod: init_module ‘/data/local/word_count. ko’ failed ( Function not implemented )

表示编译 Linux 驱动的 Linux 内核版本与当前 Android 模拟器的版本不相同,无法安装。 所以在编译 Linux 驱动时,必须选择与当前运行的 Linux 内核版本相同的 Linux 内核进行编译, 否则就 无法安装 Linux 驱动。

3>用于 Android 模拟器的 goldfish 内核默认不允许动态装载 Linux 驱动模块,因此需要在编译 Linux 内核之前执行如下命令配置 Linux 内核: cd  /kernel/goldfish

make menuconfig

4>现在执行 build.sh脚本文件完成对 word_count驱动的编译、上传和安装的工作,然后进入 Android 模拟器的终端,使用echo和dmesg命令可以测试word_count驱动和查看测试结果。

第二种方法:

1>android模拟器可以直接运行普通的Linux程序需要满足一下几个条件:

  android模拟器、开发板或手机需要有root权限。

可执行文件需要使用交叉编译器进行编译、以便支持ARM处理器。

2>现在开始测试:

   首先在/root/drivers/ch06/word_count目录中建立一个 Android.mk 文件。并输入如下的内容:

LOCAL PATH:= $ (call my-dir)

include $(CLEAR_ VARS)

#指定要编译的源代码文件

 LOCAL _SRC _FILES := test_word _count .c

 #指定模块名,也是编译后生成的可执行文件名

LOCAL_MODULE := test_word_count

 LOCAL MODULE_TAGS :=optional

include  $(BUILD_ EXECUTABLE)

LOCAL. MODULE _TAGS. 表示当前工程(Android.mk文件所在的目录)在什么模式下编译.

  其次:1.为了将 test_word_count.c 文件编译成可在 Android 模拟器上运行的可执行程序,可以将 word_count 目录复制到<Android 源代码目录〉的某个子目录,也可以在<Android 源代码目录〉目录中为 word_count目录建立一个符号链接。例如:

 ln-s/root/drivers/ch06/word_count /sources/android/android4/ development/word_ count

2.现在进入/sources/android/android4 目录,执行下面的命令初始化编译命令source ./build/envsetup .sh

3.可以使用下面两种方法编译:test_word_count.c.

(1)进入/sources/android/android4/development/word_count 目录,并执行如下的命令:mm

(2)在/sources/android/android自录下执行如下的命令:

mmm development/word_count

4.现在执行下面的命令将 test_word_count 文件上传到 Android 模拟器:

 # adb push ./emulator/test_word_count  /data/local

5.然后进入 Android 模拟器的终端,并执行下面的命令测试 word_count 驱动(需要先使用 chmod 命令设置 test_word_count 的可执行权限〉:

 # chmod 777 /data/1ocal/test _word _count

# /data/local/test_word_count

# /data/1ocal/test _word_ count ’a  bb  ccc ddd  eee ’

 执行上面的命令后, 如果输出的单词个数是 5, 表示程序测试成功。

3.使用 Android NDK 测试 Linux 驱动

4.使用 Java 代码直接操作设备文件来测试 Linux 驱动

5.使用 S3C6410 开发板测试 Linux 驱动

6.将驱动编译进 Linux 内核进行测试

使用如下的步骤将 word_count驱动加入 Linux 内核源代码树:

第 1 步:将 word_count.c 文件放入 Linux 内核源代码:将word_count.c 文件放到<Liunx内核目录〉/drvers/cbar目录中。

第 2 步:修改Kconfig 文件:

打开/root/kemel/goldfish/drivers/char/Kconfig文件,找到 endmenu,并在 eodmenu 前面添加如下代码:

 config WORD_COUNT

boo1 "word_count driver”

 help

This is a word count driver . It can get a word count  from /dev/wordcount

      第 3 步:修改 Makefile 文件

Obj-$(CONFIG_WORD_COUNT)       += word_count.O

第 4 步:设置.config 文件

第 5 步:编译 Linux 内核

进入/root/kernel/goldfish 目录,执行下面的命令编译 Linux 内核:  make

5.使用eclipse开发和测试 linux驱动程序

1> 在 Eclipse 中开发 Li nu x 驱动程序

步骤如下:

·第1步:建立C工程---第 2 步:建立C源代码文件链接[单击 word__count_eclipse 工程右键菜单中的“New">"Soruce Folder”菜单项目,打开“New Soruce Folder对话框, 在“Folder name”文本框中输入“src “--à单击 “Finish”按钮建立一个保存 Linux 驱动源代码文件的目录----单击 src 目录---右键菜单中单击 “Import”菜单项--打开 “ Import ” 对话框--选择“File System ”项---单击 "Next”按钮进入下一个设置界面--选择word_count.c--单击“advanced“-----选择“ Create links in workspace”复选框---finish]------ 第 3 步:设置 include 路径:/root/kernel/goldfish/include    /root/kernel/goldfish/arc/arm/include------第 4 步:编译 Linux 驱动。

2> 在 Eclipse 中测试 Linux 驱动

第 1 步:导入 test_word_count.c 文件---第 2 步:设置 include 路径------第 3 步:建立 Target[单击 word_count_ eclipse_ test 工程右键菜单的“Make Targets”〉“Create” 菜单项,打开 “Create Make Target”对话框,在“Target name” 文本框中输入“word_count_eclipse_test”,然后单击“OK” 按钮关闭对话框]-----第 4 步: Build 工程[单击 word_count_eclipse_test 工程右键菜单的“Make Targets" > “Build” 菜单项, 打开“Make Targets”对话框,选中在第 3 步建立的“word_count_ eclipse_test”,然后单击“Build” 按钮,会在 word_count_eclipse_test 工程中生成一些配置文件]------第 5 步; 运行测试程序[单击工程右键菜单的“Run As”>”Local C/C++  Application”菜单项]

 

posted on 2016-06-05 20:35  Y-Beatrice  阅读(315)  评论(0编辑  收藏  举报