编译和测试android的驱动程序学习笔记

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,测试结果如下图所示:


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值