0x00 前言

通过这篇文章,我们可以详细的掌握android驱动程序的编译以及对其进行测试的知识点,这里采用goldfish内核并且在android模拟器上进行测试。

0x01 准备

首先我们应该了解怎么样下载和编译android下面的linux内核,推荐一篇文章,写的很详细:http://bbs.pediy.com/showthread.php?t=192746 .。其次,由于用于android模拟器的goldfish内核默认是不允许动态加载linux驱动模块的,为了方便后面我们要讲到的测试动态加载的驱动模块,我们这里需要先配置goldfish内核允许动态加载linux驱动模块,具体方法是切换到goldfish内核根目录下执行:

make menuconfig
执行上面的命令后,会出现如下图所示的设置界面,按空格键将第二项“Enable loadable module support”选中(前面是【×】)


然后按回车键进入其子菜单,将前三项选中,如下图:

然后保存退出。

0x02 编写驱动程序以及配置文件

新建一个目录用于存放驱动程序和配置文件,文件目录结构如下图:


其中,各文件内容如下:

Makefile:

ifndef CONFIG_WORD_ECHO
obj-m := word_echo.o
else
obj-${CONFIG_WORD_ECHO} := word_echo.o
endif
Kconfig:

config WORD_ECHO
tristate "word_echo driver"
default y
help
This is a word echo driver,it can echo what you write
word_echo.c:

#include <linux/module.h>  
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "word_echo" // 定义设备文件名
static unsigned char mem[10000]; // 保存向设备文件写入的数据
static char read_flag = 'y'; // y:已从设备文件读取数据 n:未从设备文件读取数据
static int written_count = 0; // 向设备文件写入数据的字节数

// 从设备文件读取数据时调用该函数
// file:指向设备文件、buf:保存可读取的数据 count:可读取的字节数 ppos:读取数据的偏移量
static ssize_t word_echo_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
// 如果还没有读取设备文件中的数据,可以进行读取
if(read_flag == 'n')
{
// 将内核空间的数据复制到用户空间,buf中的数据就是从设备文件中读出的数据
copy_to_user(buf, (void*) mem, written_count);
// 向日志输出已读取的字节数
printk("read count:%d", (int) written_count);
// 设置数据已读状态
read_flag = 'y';
return written_count;
}
// 已经从设备文件读取数据,不能再次读取数据
else
{
return 0;
}
}
// 向设备文件写入数据时调用该函数
// file:指向设备文件、buf:保存写入的数据 count:写入数据的字节数 ppos:写入数据的偏移量
static ssize_t word_echo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
// 将用户空间的数据复制到内核空间,mem中的数据就是向设备文件写入的数据
copy_from_user(mem, buf, count);
// 设置数据的未读状态
read_flag = 'n';
// 保存写入数据的字节数
written_count = count;
// 向日志输出已写入的字节数
printk("written count:%d", (int)count);
return count;
}
// 描述与设备文件触发的事件对应的回调函数指针
// 需要设置read和write成员变量,系统才能调用处理读写设备文件动作的函数
static struct file_operations dev_fops =
{ .owner = THIS_MODULE, .read = word_echo_read, .write = word_echo_write };

// 描述设备文件的信息
static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops };

// 初始化Linux驱动
static int word_echo_init(void)
{
int ret;
// 建立设备文件
ret = misc_register(&misc);
// 输出日志信息
printk("word_echo_init_success\n");
return ret;
}

// 卸载Linux驱动
static void word_echo_exit(void)
{
// 删除设备文件
misc_deregister(&misc);
// 输出日志信息
printk("word_echo_exit_success\n");
}

// 注册初始化Linux驱动的函数
module_init( word_echo_init);
// 注册卸载Linux驱动的函数
module_exit( word_echo_exit);

MODULE_AUTHOR("parkerpeng");
MODULE_DESCRIPTION("just echo word which you write in!");
MODULE_ALIAS("word echo module.");
MODULE_LICENSE("GPL");

然后将上述目录建立一个软链接到${kernel_home}/drvicers/char/目录下(当然你也可以直接在${kernel_home}/drvicers/char/下建立word_ehco目录,就可以省去建立软链接这一步,这里我把目录放在了其它地方,以便于我自己代码管理),如下:

ln -s   ~/src/android/kernel/mydrivers/word_echo   /home/parker/src/android/kernel/goldfish/drivers/char/word_echo

0x03 修改内核配置文件

为了能让make命令找到word_echo目录中的Kconfig以及Makefile,我们需要修改上级目录也就是${kernel_home}/drivers/char/中的Kconfig以及Makefile文件,让他们包含word_echo目录下的Kconfig以及Makefile。

打开${kernel_home}/drivers/char/目录下的Kconfig,在文件末尾“endmenu”之前添加如下一行代码:

source "drivers/char/word_echo/Kconfig"
打开${kernel_home}/drivers/char/目录下的Makefile,在添加如下一行:

obj-$(CONFIG_WORD_ECHO)+= word_echo/

然后我们需要修改内核根目录下.config文件,添加CONFIG_WORD_ECHO变量并且给它赋值,这些值可以是:

m:将驱动编译成可供内核动态加载的ko模块

y:将驱动编译进内核

n:将该驱动从内核剔除

可以手动在.config文件中给CONFIG_WORD_EHCO赋值,也可以通过在内核根目录下输入make menuconfig命令给它赋值,它会自动修改.config文件中的该变量。

输入make menuconfig命令后,选择“Device Driver”---------->“Character devices”---------->"word_echo driver",按空格键在<>,<*>,<M>三种值之间切换,它们分别表示上述的n,y,m三个值,如下图所示:

这里选择将驱动模块编译进内核,保存设置后,就可以切换到内核根目录下执行make命令进行编译了。

0x04 测试驱动程序

由于前面选择的是将驱动程序编译进内核,因此内核会自动加载该驱动程序,在${kernel_home}/arch/arm/boot目录下找到编译好的内核zimage,执行以下命令运行模拟器:

emulator -avd AVD_XXXX -kernel zImage -system system.img -data userdata.img -ramdisk ramdisk.img
上面命令中system.img,userdata.img,ramdisk.img是我在编译好的android4.4.2文件

接着进入adb shell,测试结果如下图所示:


更多相关文章

  1. android 文件读取(assets)
  2. 编译Android4.3内核源代码
  3. JAVA环境下创建JSP文件报错: The superclass "javax.servlet.http
  4. 【JavaWeb-6】HttpServletResponse的字符字节输出流、编码、文件
  5. Java 简单解决springmvc获取properties文件里面中文内容出现论码
  6. 解决Eclipse建立Maven项目后无法建立src/main/java资源文件夹的
  7. java读写中文文件
  8. java文件上传输入输出流的问题
  9. Android MediaCodec硬解码AAC音频文件(实时AAC音频帧)并播放

随机推荐

  1. Android常用控件总结
  2. Android EditText 共用TextWatcher,在Text
  3. android 桌面快捷方式
  4. android各种分辨率和屏幕密度
  5. Android中Binder类代码(android-5.0.2)
  6. 史上最懒的android开发环境配置教程
  7. android service完全解析。
  8. android Vibrator 使用
  9. android broadcast intent
  10. android webview ERR_UNKNOWN_URL_SCHEME