嵌入式LINUX驱动学习之4.字符设备驱动编程(一)
一、字符设备操作接口数据结构:truct file_operations
1.1 头文件
#include <linux/fs.h>
struct file_operations {
struct module *owner;
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
};
1.1.1THIS_MODULE宏实现
#ifdef MODULE
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else
#define THIS_MODULE ((struct module *)0)
#endif
1.2 struct file_operations结构体使用
#include <linux/fs.h>
ssize_t mychar_dev_open(struct inode * inode, struct file * file){
}
ssize_t mychar_dev_close(struct inode * inode,struct file * file){
}
ssize_t mychar_dev_read(struct file * file,char __user * buf,\
size_t count,loff_t * ppos){
char kbuf[count];
memset(kbuf,0,count);
copy_to_user(buf,kbuf,count);
}
ssize_t mychar_dev_write(struct file * file ,const char __user *buf,\
size_t count, loff_t *ppos)
{
char kbuf[count];
memset(kbuf,0,count);
copy_from_user(kbuf,buf,count);
}
struct file_operations mychar_dev_fops = {
.owner = THIS_MODULE,
.open = mychar_dev_open,
.release = mychar_dev_close,
.read = mychar_dev_read,
.write = mychar_dev_write,
};
1.2.1用户空间和内核之间进行数据传输的函数:copy_to_user() 、 copy_from_user()
#include <asm/uaccess.h>
int copy_to_user(void __user *to, const void *from, int n);
EXPORT_SYMBOL(copy_to_user);
int copy_from_user(void *to, const void __user *from, int n);
EXPORT_SYMBOL(copy_from_user);
二、定义初始化字符设备对象
2.1头文件
#include <linux/cdev.h>
void cdev_init(struct cdev *cdev, const struct file_operations *fops);
2.2函数实现(了解即可)
#include <linux/cdev.h>
struct cdev file_dev;
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
memset(cdev, 0, sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
kobject_init(&cdev->kobj, &ktype_cdev_default);
cdev->ops = fops;
}
头文件位置:include/linux/list.h
#include <linux/list.h>
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
三、向内核添加注册字符设备对象:cdev_add()
1.4.1 头文件
#include <linux/cdev.h>
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
1.4.2 函数实现
#include <linux/cdev.h>
static struct kobj_map *cdev_map;
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
p->dev = dev;
p->count = count;
return kobj_map(cdev_map, dev, count,\
NULL, exact_match, exact_lock, p);
}
四、向内核添加卸载字符设备对象:cdev_del()
4.1 头文件
#include <linux/cdev.h>
void cdev_del(struct cdev *);