1.Linux字符设备驱动结构
1.1 cdev结构体
Linux内核中使用cdev结构体描述一格字符设备
struct cdev{
struct kobject kobj;
struct module *owner; /*所属模块*/
struct file_operations *ops; /*文件操作结构体*/
struct list_head list;
dev_t dev; /*设备号,前12位主设备号,后20位次设备号*/
unsigned int count;
}
struct module结构体 和 THIS_MODULE详解
1.2 cdev操作函数
初始化函数cdev_init() /建立file_operations和cdev之间的关系
void cdev_init(struct cdev *cdev,struct file_operations *fops)
{
memset(cdev,0,sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
kobject_init(&cdev->kobj,&ktype_cdev_default);
cdev->ops=fops
}
分配和释放设备号
调用cdev_add()向系统注册字符设备前,需要使用函数申请设备号,这两个函数分别为:
- int register_chrdev_region(dev_t from,unsigned count,const char *name);
(用于一直起始设备的设备号的情况) - int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count);
(用于设备号未知的情况, 调用成功后把得到的设备号放入第一个参数dev中)
1.3Linux字符驱动设备驱动的组成
字符设备驱动读,写,IO控制函数模板:xxx_read(),xxx_write(),xxx_ioctl()
/*xxx为字符设备名*/
/*filp文件结构体指针,
*buf:用户空间内的缓存地址,
count:要读的字节数,
*f_pos要读的位置相对于开头的偏移*/
ssize_t xxx_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
...
copy_to_user(buf,...,...);//内核空间复制到用户缓存区
...
}
ssize_t xxx_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos)
{
...
copy_from_user(...,buf,...);//用户空间缓存区复制到内核空间
...
}
/*ioctl函数*/
long xxx_ioctl(struct file *filep,unsigned int cmd,unsigned long arg)
{
...
switch (cmd){
case xxx_cmd1:
...
berak;
case xxx_cmd2:
...
break;
default://不能支持的命令
return -ENOTTY;
}
return 0;
}
定义字符设备文件操作函数 xxx_fops
struct file_operations xxx_fops={
.owner=THIS_MODULE,
.read=xxx_read,
.write=xxx_write,
.unlocked_ioctl=xxx_ioctl,
...
}
驱动加载,卸载函数:xxx_init(),xxx_exit()
//设备结构体
struct xxx_dev_t{
struct cdev cdev;
...
}xxx_dev;
//设备驱动加载函数
static int __init xxx_init(void)
{
...
cdev_init(&xxx_dev.cdev,&xxx_fops);
xxx_dev.cdev.owner=THIS_MODULE;
//获取字符设备号
if(xxx_major){
register_chrdev_region(xxx_dev_n0,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);
...
}