我的第一个字符驱动刚刚写好,摸摸还是热的~n_n 先做个总结吧,免得忘了!
编写一个字符设备驱动大概分为三个部分:
1.驱动程序本身,一个.c文件
2.Makefile文件
3.测试程序
一.字符驱动
以下是程序的清单,这个驱动的功能非常简单,先将保存的数据打印出来,然后提示用户输入,讲输入的信息保存到内核态,下面通过代码那的注释以说明
/*在这个程序的末尾有两个函数 module_init(GlobalChar_init);
module_exit(GlobalChar_exit);
同C程序不同,驱动程序不是从main()开始的,而是通过两个宏告诉系统程序的入口,即GlobalChar_init这个函数,下面那个是退出的函数,程序初始化的时候会自动调用GlobalChar_init
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");//
MODULE_AUTHOR("LIU");//作者姓名
#define DEV_NAME "GlobalChar"//设备名称
static ssize_t GlobalRead(struct file *,char *,size_t,loff_t*);
static ssize_t GlobalWrite(struct file *,const char *,size_t,loff_t*);
static int char_major =0;
static int GlobalData =0;
//初始化字符驱动的file_operation结构
struct file_operations globalchar_fops =
{
.read =GlobalRead,
.write =GlobalWrite
};//定义的设备结构,返回两个程序指针
//模块初始化
static int __init GlobalChar_init(void)
{
int ret;
ret = register_chrdev(char_major,DEV_NAME,&globalchar_fops);//注册设别驱动
//这是操作系统提供的一个API,通过这个函数来注册一个字符型的设备,参数是 (主设备号,字符设备名,设备结构)
if(ret<0)
{
//在驱动中没有stdio的头文件,所以用不了printf()
printk(KERN_ALERT "GlobalChar REG FAIL!/n");
}
else
{
printk(KERN_ALERT "GlobalChar REG Success!/n");
char_major=ret;
printk(KERN_ALERT "MAJOR = %d/n",char_major);
}
return ret;
}
//模块卸载函数
static void __exit GlobalChar_exit(void)
{
unregister_chrdev(char_major,DEV_NAME);//注销设备
return;
}
//设备驱动read函数
static ssize_t GlobalRead(struct file *filp,char *buf,size_t len,loff_t *off)//注意这个函数的格式,都是系统定义的
{
if(copy_to_user(buf,&GlobalData,sizeof(int)))//从内核复制GlobalData到用户空间,因为这个程序是运行在内核态的,所以调到用户态的话,要中这个函数
{
return -EFAULT;
}
return sizeof(int);
}
//驱动设备writt函数
static ssize_t GlobalWrite(struct file *filp,const char *buf,size_t len,loff_t *off)
{
if(copy_from_user(&GlobalData,buf,sizeof(int)))
{
return -EFAULT;
}
return sizeof(int);
}
module_init(GlobalChar_init);
module_exit(GlobalChar_exit);
//
二、Makefile的编写
首先Makefile文件需要和上面编写的驱动放在一个文件夹里面,当执行make命令的时候系统会自动寻找文件夹下面的Makefile文件然后执行,Makefile文件有一定的语法和格式,这部分具体我没有研究,先把代码贴上:
ifneq ($(KERNELRELEASE),)
obj-m:=GlobalCharDev.o
else
KERNELDIR=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko
endif
########################################################
OK !Makefile文件写好了,然后在命令提示符下面输入make,出现如下提示:
1.make文件
dickens@ubuntu:~/example$ make
make -C /lib/modules/2.6.35-22-generic/build M=/home/dickens/example modules
make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.35-22-generic'
CC [M] /home/dickens/example/GlobalCharDev.o
Building modules, stage 2.
MODPOST 1 modules
LD [M] /home/dickens/example/GlobalCharDev.ko
make[1]:正在离开目录 `/usr/src/linux-headers-2.6.35-22-generic'