一、字符设备驱动的结构体描述
1、描述字符设备的结构struct cdev
struct cdev {
struct kobject kobj;//内嵌的kobject 对象
struct module *owner;//所属模块
const struct file_operations *ops;//文件操作结构体
struct list_head list;//链表头
dev_t dev;//设备号
unsigned int count;
};
2、文件操作函数集合struct file_operations
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
二、字符设备驱动模板
/*xxx 设备结构体*/
struct xxx_dev
{
struct cdev cdev; /*cdev 结构体*/
...
};
struct xxx_dev *xxx_devp; /*设备结构体指针*/
int xxx_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp->private_data = xxx_devp;
...
return 0;
}
/*文件释放函数*/
int xxx_release(struct inode *inode, struct file *filp)
{
...
return 0;
}
/* ioctl 设备控制函数 */
static int xxx_ioctl(struct inode *inodep, struct file *filp, unsigned
int cmd, unsigned long arg)
{
struct xxx_dev *dev = filp->private_data;/*获得设备结构体指针*/
switch (cmd)
{
...
}
return 0;
}
/*读函数*/
static ssize_t xxx_read(struct file *filp, char _ _user *buf, size_t size,
loff_t *ppos)
{
struct xxx_dev *dev = filp->private_data; /*获得设备结构体指针*/
...
}
/*写函数*/
static ssize_t xxx_write(struct file *filp, const char _ _user *buf,
size_t size, loff_t *ppos)
{
struct xxx_dev *dev = filp->private_data; /*获得设备结构体指针*/
...
}
/*文件操作结构体*/
static const struct file_operations globalmem_fops =
{
.owner = THIS_MODULE,
.read = xxx_read,
.write = xxx_write,
.ioctl = xxx_ioctl,
.open = xxx_open,
.release = xxx_release,
...
};
/*初始化并注册cdev*/
static void xxx_setup_cdev(struct xxx_dev *dev, int index)
{
int err, devno = MKDEV(xxx_major, index);
cdev_init(&dev->cdev, &xxx_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &xxx_fops;
err = cdev_add(&dev->cdev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding LED%d", err, index);
}
/*设备驱动模块加载函数*/
int xxx_init(void)
{
int result;
dev_t devno = MKDEV(xxx_major, 0);
/* 申请设备号*/
if (xxx_major)
result = register_chrdev_region(devno, 1, "xxx");
else /* 动态申请设备号 */
{
result = alloc_chrdev_region(&devno, 0, 1, "xxx");
xxx_major = MAJOR(devno);
}
if (result < 0)
return result;
/* 动态申请设备结构体的内存*/
xxx_devp = kmalloc(sizeof(struct xxx_dev), GFP_KERNEL);
if (!xxx_devp) /*申请失败*/
{
result = - ENOMEM;
goto fail_malloc;
}
memset(xxx_devp, 0, sizeof(struct xxx_dev));
xxx_setup_cdev(xxx_devp, 0);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
module_init(xxx_init);
module_exit(xxx_exit);
1、描述字符设备的结构struct cdev
struct cdev {
struct kobject kobj;//内嵌的kobject 对象
struct module *owner;//所属模块
const struct file_operations *ops;//文件操作结构体
struct list_head list;//链表头
dev_t dev;//设备号
unsigned int count;
};
2、文件操作函数集合struct file_operations
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
二、字符设备驱动模板
/*xxx 设备结构体*/
struct xxx_dev
{
struct cdev cdev; /*cdev 结构体*/
...
};
struct xxx_dev *xxx_devp; /*设备结构体指针*/
int xxx_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp->private_data = xxx_devp;
...
return 0;
}
/*文件释放函数*/
int xxx_release(struct inode *inode, struct file *filp)
{
...
return 0;
}
/* ioctl 设备控制函数 */
static int xxx_ioctl(struct inode *inodep, struct file *filp, unsigned
int cmd, unsigned long arg)
{
struct xxx_dev *dev = filp->private_data;/*获得设备结构体指针*/
switch (cmd)
{
...
}
return 0;
}
/*读函数*/
static ssize_t xxx_read(struct file *filp, char _ _user *buf, size_t size,
loff_t *ppos)
{
struct xxx_dev *dev = filp->private_data; /*获得设备结构体指针*/
...
}
/*写函数*/
static ssize_t xxx_write(struct file *filp, const char _ _user *buf,
size_t size, loff_t *ppos)
{
struct xxx_dev *dev = filp->private_data; /*获得设备结构体指针*/
...
}
/*文件操作结构体*/
static const struct file_operations globalmem_fops =
{
.owner = THIS_MODULE,
.read = xxx_read,
.write = xxx_write,
.ioctl = xxx_ioctl,
.open = xxx_open,
.release = xxx_release,
...
};
/*初始化并注册cdev*/
static void xxx_setup_cdev(struct xxx_dev *dev, int index)
{
int err, devno = MKDEV(xxx_major, index);
cdev_init(&dev->cdev, &xxx_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &xxx_fops;
err = cdev_add(&dev->cdev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding LED%d", err, index);
}
/*设备驱动模块加载函数*/
int xxx_init(void)
{
int result;
dev_t devno = MKDEV(xxx_major, 0);
/* 申请设备号*/
if (xxx_major)
result = register_chrdev_region(devno, 1, "xxx");
else /* 动态申请设备号 */
{
result = alloc_chrdev_region(&devno, 0, 1, "xxx");
xxx_major = MAJOR(devno);
}
if (result < 0)
return result;
/* 动态申请设备结构体的内存*/
xxx_devp = kmalloc(sizeof(struct xxx_dev), GFP_KERNEL);
if (!xxx_devp) /*申请失败*/
{
result = - ENOMEM;
goto fail_malloc;
}
memset(xxx_devp, 0, sizeof(struct xxx_dev));
xxx_setup_cdev(xxx_devp, 0);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
module_init(xxx_init);
module_exit(xxx_exit);