一个完整的test字符设备驱动程序,以下给出模块加载卸载方法以及简单的测试程序。
首先编写一个test.h,定义各个接口函数以及包含的头文件:
#define __NO_VERSION__
#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <asm/page.h>
static ssize_t read_test(struct file *file,char *buf,size_t count,loff_t *ppos);
static ssize_t write_test(struct file *file,const char *buf,size_t count,loff_t *ppos);
static int open_test(struct inode *inode,struct file *file);
static int release_test(struct inode *inode,struct file *file);
struct file_operations test_fops={
owner: THIS_MODULE,
read: read_test,
write: write_test,
open: open_test,
release: release_test,
};
char kernel_version[]=UTS_RELEASE;
源代码test.c如下:
#include "test.h"
unsigned int test_major = 0;
MODULE_LICENSE("GPL");
static ssize_t read_test(struct file *file,char *buf,size_t count,loff_t *ppos)
{
size_t left;
/* int x=sizeof(buf);*/
if(verify_area(VERIFY_WRITE,buf,count)==-EFAULT)
return EFAULT;
for(left=count;left>0;left--)
{
__put_user(1,buf); //将1从内核空间拷到用户空间
buf++;
}
return count;
}
static ssize_t write_test(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
return count;
}
static int open_test(struct inode *inode,struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
static int release_test(struct inode *inode,struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
int init_module(void)
{
int result;
result=register_chrdev(0,"test",&test_fops); //注册字符设备模块,动态分配主设备号
if(result<0)
{
printk(KERN_INFO"test:cant get major number\n");
return result;
}
if(test_major==0)
test_major=result;
return 0;
}
void cleanup_module(void)
{
unregister_chrdev(test_major,"test");
}
源代码编译加载方法如下:首先还是要确保linux内核源代码放在/usr/src里面,编译源代码:gcc -O2 -DMODULE -D__KERNEL__ -I/usr/src/linux/include -c test.c
编译结果为test.o,加载模块:insmod test.o,加载成功可以在/proc/drivers下面看到test模块,其中主设备号动态分配为253,接下来建立节点:mknod /dev/test c 253 0,在/dev下建立test节点,c表示test模块为字符设备,253为主设备号,在/proc/driver里面可以找到,0为从设备号。建立节点成功后可以查找一下test模块,在/dev 下面 find -name test。
编写一个简单的测试程序:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int testdev;
int i;
char buf[10];
testdev=open("/dev/test",O_RDWR);
if(testdev==-1)
{
printf("cant open file\n");
exit(0);
}
read(testdev,buf,10);
for(i=0;i<9;i++)
{printf("%d",buf[i]);}
printf("%d\n",buf[9]);
close(testdev);
}
编译gcc -o test_app test_app.c,运行./test_app,打印出来的一概是十个1。
卸载test模块:rmmod test,打完收工 :-)