//字符设备的结构体
struct xxx_dev_t
{
struct cdev cdev;
...........
}xxx_dev;
//字符设备模块的加载和卸载函数
static int __init xxx_init(void)
{
.......
/*初始化cdev*/
cdev_init(&xxx_dev.cdev,&xxx_fops);
xxx_dev.owner=THIS_MODULE;
/*获取字符设备号*/
if(xxx_major)
{
/*为一个字符驱动获取一个或多个设备编号*/
register_chrdev_region(xxx_dev_no,1,DEV_NAME);
}
else {
alloc_chrdev_region(&xxx_dev_no,0,1,DEV_NAME);
}
ret=cdev_add(&xxx_dev.cdev,xxx_dev_no,1);
........
}
//设备驱动模块的卸载函数
static void __exit xxx_exit(void)
{
unregister_chrdev_region(xxx_dev_no,1);//注释占用设备号
cdev_del(&xxx_dev.cdev);
............
}
//字符设备驱动的file_operations结构体中的成员函数
/*读设备*/
ssize_t xxx_read(struct file *filp,char __usr *buf,size_t count,loff_t *f_pos)
{
............
copy_to_user(buf,...,...);
.............
}
/*写设备*/
ssize_t xxx_write(struct file *filp,const char __usr *buf,size_f count,loff_t *f_pos)
{
..............
copy_from_user(....,buf,....);
..............
}
/*ioctl函数*/
int xxx_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
.............
switch(cmd)
{
case xxx_cmd1:
..........;break;
case xxx_cmd2:
...........;break;
..............
default: /*不能支持的命令*/
return -ENOTTY;
}
return0;
}
//内核空间和用户空间交互,经常用到的两个函数
unsigned long copy_from_user(void *to,const void __user *from,unsigned long count);
unsigned long copy_to_usr(void __user *to,const void *from,unsigned long count);
/*上述函数均返回不能被复制的字节数,如果完全复制成功,则返回值为0。*/