Android内核开发 内核模块编程编译及安卓虚拟机测试
本文出处: http://blog.csdn.net/leytton/article/details/52736829
1、配置交叉编译环境
见《Android内核开发 Goldfish Linux Kernel编译及安卓虚拟机测试》
2、word_count.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_count" //保存读写字符串 static unsigned char mem[1000]; //读写字符串中字符数量,ssize_t有符号int,size_t无符号int static ssize_t char_count=0; // 从设备文件读取数据时调用该函数 // file:指向设备文件、buf:保存可读取的数据 count:可读取的字节数 ppos:读取数据的偏移量 static ssize_t word_count_read(struct file *file,char __user *buf,size_t read_count,loff_t *ppos) { read_count = char_count; //printk("read:debug:%d\n",(int)char_count); // 将内核空间的数据复制到用户空间,buf中的数据就是从设备文件中读出的数据 if(copy_to_user(buf, (void*)mem,read_count)){ return -EINVAL; } printk("read:read_count:%d\n",(int)read_count); char_count=0; return read_count; } // 向设备文件写入数据时调用该函数 // file:指向设备文件、buf:保存写入的数据 count:写入数据的字节数 ppos:写入数据的偏移量 static ssize_t word_count_write(struct file *file,const char __user *buf,size_t write_count,loff_t *ppos) { char_count=write_count; // 将用户空间的数据复制到内核空间,mem中的数据就是向设备文件写入的数据 if(copy_from_user((void*)mem,buf,write_count)){ return -EINVAL; } mem[write_count]='\0'; printk("count_write:write_count:%d\n",(int)char_count); return char_count; } static struct file_operations dev_fops= {.owner=THIS_MODULE, .read=word_count_read, .write=word_count_write}; static struct miscdevice misc= {.minor=MISC_DYNAMIC_MINOR, .name=DEVICE_NAME, .fops=&dev_fops}; //Linux驱动装载函数 static int __init word_count_init(void) { int ret; //注册设备文件 ret=misc_register(&misc); printk("word_count init success!"); return ret; } //Linux驱动卸载函数 static void __exit word_count_exit(void) { // 注销(移除)设备文件 misc_deregister(&misc); printk("word_count exit success!"); } //注册装载函数 module_init(word_count_init); //注册卸载函数 module_exit(word_count_exit); MODULE_AUTHOR("Leytton"); MODULE_DESCRIPTION("A simple Word Count Driver"); MODULE_ALIAS("a simplest module"); MODULE_LICENSE("MIT");
3、Makefile文件
注意Linux kernel源码目录需要提前编译,否则内核模块会编译出错。见《Android内核开发 Goldfish Linux Kernel编译及安卓虚拟机测试》
TARGET=word_count KDIR=/mnt/workbench/android-goldfish-3.4 #Linux kernel源码目录 PWD=$(shell pwd) ARCH=arm CROSS_COMPILE=arm-linux-androideabi- CC=$(CROSS_COMPILE)gcc LD=$(CROSS_COMPILE)ld obj-m:=$(TARGET).o default: make EXTRA_CFLAGS="-D_CONFIG_ARM_ -fno-pic" -C $(KDIR) M=$(PWD) modules clean: rm -f *.o *.mod.o *.mod.c *.symvers *.order
make编译
make clean清除编译过程中生成的垃圾文件
【注意 测试时不加EXTRA_CFLAGS="-D_CONFIG_ARM_ -fno-pic" 加载内核模块时会出现错误 insmod: init_module 'word_count.ko' failed (Exec format error)】
4、adb连接Android虚拟机加载内核模块
adt-bundle-linux-x86_64-20140702/sdk/platform-tools目录下 [hadoop@localhost platform-tools]$ ./adb push word_count.ko /llqqww/ 130 KB/s (5968 bytes in 0.044s) [hadoop@localhost platform-tools]$ ./adb shell root@generic:/ # dmesg -c 255|root@generic:/ #insmod /llqqww/word_count.ko root@generic:/ # echo hello > /dev/word_count root@generic:/ # cat /dev/word_count hello root@generic:/ # root@generic:/ # rmmod word_count.ko root@generic:/ # dmesg word_count init success! count_write:write_count:6 <4>read:read_count:6 <4>read:read_count:0 <4>word_count exit success! root@generic:/ #