红联Linux门户
Linux帮助

Android内核开发 Linux C编程调用内核模块设备驱动

发布时间:2016-10-06 11:26:49来源:blog.csdn.net/leytton作者:Leytton
本文目的为Linux系统环境下:
1、编写内核模块程序并编译
2、加载内核模块
3、编写C程序调用内核模块
 
功能为向内核模块虚拟设备写如字符串,再从内核模块虚拟设备读出字符串长度。
 
1、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)){  
if(copy_to_user(buf, &char_count,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("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!");  
}
 
2、Makefile文件
TARGET=word_count  
KDIR=/usr/src/kernels/3.10.0-327.el7.x86_64 # centos  
PWD=$(shell pwd)  
obj-m:=$(TARGET).o  
default:  
make -C $(KDIR) M=$(PWD) modules  
clean:  
rm -f *.o *.mod.o *.mod.c *.symvers *.order  
 
3、word_count_test.c文件
#include <stdio.h>  
#include <fcntl.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <string.h>  
int main( int argc, char *argv[] )  
{  
/* 打开设备文件(/dev/word_count)的句柄 */  
int devret;  
int word_count=0;  
int write_count=0;  
/* 打开设备文件 */  
devret = open( "/dev/word_count", O_RDWR );  
/*  如果open函数返回-1,表示打开设备文件失败 */  
if ( devret == -1 )  
{  
printf( "Cann't open file \n" );  
return(0);  
}  
/* 
*  如果word_count_test后面跟有命令行参数,程序会将第1个参数值当作待统计的字符串 
*  如果没有命令行参数,则只读取设备文件中的值 
*/  
if ( argc > 1 )  
{  
/*  向设备文件写入待统计的字符串 */  
write_count=write( devret, argv[1], strlen( argv[1] ) );  
/*  输出待统计的字符串 */  
printf( "write string:%s,count:%d\n", argv[1],write_count );  
}  
//  读取设备文件中的单词数  
read(devret, &word_count, sizeof(word_count));
//  输出统计出的单词数
printf("word count:%d\n", word_count);  
/*  关闭设备文件 */  
close( devret );  
return(0);  
}
//注册装载函数  
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");  
 
4、编译内核模块
[hadoop@localhost drivers01]$ make  
make -C /usr/src/kernels/3.10.0-327.el7.x86_64   M=/mnt/workbench/workspace/drivers01 modules  
make[1]: 进入目录“/usr/src/kernels/3.10.0-327.el7.x86_64”  
CC [M]  /mnt/workbench/workspace/drivers01/word_count.o  
Building modules, stage 2.  
MODPOST 1 modules  
CC  /mnt/workbench/workspace/drivers01/word_count.mod.o  
LD [M]  /mnt/workbench/workspace/drivers01/word_count.ko  
make[1]: 离开目录“/usr/src/kernels/3.10.0-327.el7.x86_64”  
[hadoop@localhost drivers01]$   
 
5、加载内核模块
[hadoop@localhost drivers01]$ sudo insmod word_count.ko   
[sudo] password for hadoop:   
[hadoop@localhost drivers01]$  
 
6、编译word_count_test.c文件
gcc word_count_test.c -o word_count_test  
 
7、执行word_count_test
[hadoop@localhost drivers01]$ sudo ./word_count_test hello12345  
write string:hello12345,count:10  
word count:10
注意要用root权限执行,否则会返回以下错误
[hadoop@localhost drivers01]$ ./word_count_test hello12345
Cann't open file 
 
8、查看内核模块日志
[hadoop@localhost drivers01]$sudo dmesg -c  
[15074.261371] write:write_count:10  
[15074.261415] read:read_count:10
 
本文永久更新地址:http://www.linuxdiyf.com/linux/24792.html