1.在pc linux上安装arm-none-linux-gnueabi 交叉编译器,此编译器为android专用。而不同于arm-linux-gcc.
2.编写驱动代码:word_count.c
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "wordcount" // 定义设备文件名
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_count_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_count_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_count_read, .write = word_count_write };
// 描述设备文件的信息
static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops };
// 初始化Linux驱动
static int word_count_init(void)
{
int ret;
// 建立设备文件
ret = misc_register(&misc);
// 输出日志信息
printk("word_count_init_success\n");
return ret;
}
// 卸载Linux驱动
static void word_count_exit(void)
{
// 删除设备文件
misc_deregister(&misc);
// 输出日志信息
printk("word_init_exit_success\n");
}
// 注册初始化Linux驱动的函数
module_init( word_count_init);
// 注册卸载Linux驱动的函数
module_exit( word_count_exit);
MODULE_AUTHOR("lining");
MODULE_DESCRIPTION("statistics of word count.");
MODULE_ALIAS("word count module.");
MODULE_LICENSE("GPL");
3.参考上一篇编译生成对应ok6410 android 开发板内核的驱动文件,生成word_count.ko文件,并移植到开发板。
4.编写测试程序:test_word_count.c
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int testdev; // 打开设备文件(/dev/wordcount)的句柄
unsigned char buf[4]; // 表示单词数的4个字节
// 打开设备文件
testdev = open("/dev/wordcount", O_RDWR);
// 如果open函数返回-1,表示打开设备文件失败
if (testdev == -1)
{
printf("Cann't open file \n");
return 0;
}
// 如果test_word_count后面跟有命令行参数,程序会将第1个参数值当作待统计的字符串
// 如果没有命令行参数,则只读取设备文件中的值
if (argc > 1)
{
// 向设备文件写入待统计的字符串
write(testdev, argv[1], strlen(argv[1]));
// 输出待统计的字符串
printf("string:%s\n", argv[1]);
}
// 读取设备文件中的单词数(4个字节)
read(testdev, buf, 4);
int n = 0; // 单词数
// 将4个字节还原成int类型的值
n = ((int) buf[0]) << 24 | ((int) buf[1]) << 16 | ((int) buf[2]) << 8
| ((int) buf[3]);
// 分别输出从设备文件获取的4个字节的值
printf("word byte display:%d,%d,%d,%d\n", buf[0], buf[1], buf[2], buf[3]);
// 输出统计出的单词数
printf("word count:%d\n", n);
// 关闭设备文件
close(testdev);
return 0;
}
5.使用交叉编译工具编译
# arm-none-linux-gnueabi-gcc test_word_count.c -o test_word_count -static
生成test_word_count ,并把test_word_count 移植到开发板。
-static选项在这里是必须的,否则会出现”not found”的错误。
6.在开发板执行
/ # insmod word_count.ko
word_count_init_success
/ # ./test_word_count wangben
written count:7read count:7string:wangben
word byte display:119,97,110,103
word count:2002873959
/ # rmmod word_count
word_init_exit_success
/ #
好了,驱动已经测试完毕。