Android本质上是基于Linux内核的系统,也就是说Android就是一种Linux操作系统。只不过大多数时候都会运行在ARM架构的设备上,例如,Android手机、平板等。Android驱动实际上就是Linux驱动,只是这里使用Android深度探索(卷1):安装C/C++交叉编译环境 介绍的交叉编译器将Linux驱动编译成了ARM架构的,所以驱动可以安装在Android模拟器、Android手机(需要root)或平板上(这些设备 都要使用给予ARM架构的CPU),当然,使用传统的GCC也可以编译成X86架构的驱动(并不需要修改代码),这样也可以在Ubuntu Linux上安装Linux驱动。
本文及后面几篇文章主要介绍如何利用Android模拟器和S3C6410开发板开发给予ARM架构的Linux驱动,当然,测试的环境是 Android,而不是我们通常使用的Ubuntu Linux等X86架构的系统。最后会介绍通过多种方式测试这个驱动,测试方法包括命令行、NDK、Android程序(Java代码)等,当然,在最最 后还会介绍如果将驱动嵌入到LInux内核中,这样Android在启动是就自动拥有了这个驱动。
想学习Android底层开发的童鞋可以通过本文完全掌握开发基于Android的LInux驱动的完整步骤。在《Android深度探索(卷1):HAL与驱动开发》随书光盘上有完整的实验环境(VMWare Ubuntu Linux12.04LTS),如果嫌自己配置麻烦,可以从光盘中复制该虚拟环境,虚拟文件太大(3.6G),传不上去,只能发文章了!
一、Linux驱动到底是个什么东西
对于从未接触过驱动开发的程序员可能会感觉Linux驱动很神秘。感觉开发起来会很复杂。其实这完全是误解。实际上Linux驱动和普通的LinuxAPI没有本质的区别。只是使用Linux驱动的方式与使用Linux API的方式不同而已。
在学习Linux驱动之前我们先来介绍一下Linux驱动的工作方式。如果读者以前接触过Windows或其他非Unix体系的操作系统,最好将它们的工作方式暂时忘掉,因为这些记忆会干扰我们理解Linux底层的一些细节。
Linux驱动的工作和访问方式是Linux的亮点之一,同时受到了业界的广泛好评。Linux系统将每一个驱动都映射成一个文件。这些文件称为设备文件 或驱动文件,都保存在/dev目录中。这种设计理念使得与Linux驱动进行交互就像与普通文件进行交互一样容易。当然,也比访问LinuxAPI更容 易。由于大多数Linux驱动都有与其对应的设备文件,因此与Linux驱动交换数据就变成了与设备文件交换数据。例如,向Linux打印机驱动发送一个 打印命令,可以直接使用C语言函数open打开设备文件,再使用C语言函数ioctl向该驱动的设备文件发送打印命令。
当然,要编写Linux驱动程序还需要更高级的功能。如向打印机驱动写入数据时,对于打印机驱动来说,需要接收这些被写入的数据,并将它们通过PC的并 口、USB等端口发送给打印机。要实现这一过程就需要Linux驱动可以响应应用程序传递过来的数据。这就是Linux驱动的事件,虽然在C语言里没有事 件的概念,但却有与事件类似的概念,这就是回调(callback)函数。因此,编写Linux驱动最重要的一步就是编写回调函数,否则与设备文件交互的 数据将无法得到处理。图6-1是应用软件、设备文件、驱动程序、硬件之间的关系。