Linux字符设备驱动框架字符设备驱动框架
字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字
符设备,常见的字符设备包括鼠标、键盘、显示器、串口等等,当我们执行ls -l /dev的时候,就能看到大量的设备文件,c就
是字符设备,b就是块设备,网络设备没有对应的设备文件。编写一个外部模块的字符设备驱动,除了要实现编写一个模块所
需要的代码之外,还需要编写作为一个字符设备的代码。
驱动模型
Linux一切皆文件,那么作为一个设备文件,它的操作方法接口封装在struct file_operations,当我们写一个驱动的时候,一定
要实现相应的接口,这样才能使这个驱动可用,Linux的内核中大量使用"注册+回调"机制进行驱动程序的编写,所谓注册回
调,简单的理解,就是当我们open一个设备文件的时候,其实是通过VFS找到相应的inode,并执行此前创建这个设备文件时
注册在inode中的open函数,其他函数也是如此,所以,为了让我们写的驱动能够正常的被应用程序操作,首先要做的就是实
现相应的方法,然后再创建相应的设备文件。
#include <linux/cdev.h> //for struct cdev
#include <linux/fs.h> //for struct file
#include <asm-generic/uaccess.h> //for copy_to_user
#include <linux/errno.h> //for error number
static int ma = 0;
static int mi = 0;
const int count = 3;/* 准备操作方法集 *//*
struct file_operations {
struct module *owner; //THIS_MODULE
//读设备
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
//写设备
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
//映射内核空间到用户空间
int (*mmap) (struct file *, struct vm_area_struct *);
//读写设备参数、读设备状态、控制设备
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
//打开设备
int (*open) (struct inode *, struct file *);
//关闭设备
int (*release) (struct inode *, struct file *);
//刷新设备
int (*flush) (struct file *, fl_owner_t id);
//文件定位
loff_t (*llseek) (struct file *, loff_t, int);
//异步通知
int (*fasync) (int, struct file *, int);
//POLL机制
unsigned int (*poll) (struct file *, struct poll_table_struct *);
。。。
};
*/
ssize_t myread(struct file *filep, char __user * user_buf, size_t size,
loff_t* offset)
{ return 0;
}
struct file fops = {
.owner = THIS_MODULE,
.read = myread,
...
};/* 字符设备对象类型
struct cdev {
struct kobject kobj;
struct module *owner; //模块所有者(THIS_MODULE),用于模块计数
const struct file_operations *ops;//操作方法集(分工:打开、关闭、读/写、...)
struct list_head list;
dev_t dev; //设备号(第一个)
unsigned int count; //设备数量
};
*/static int __init chrdev_init(void){
... /* 构造cdev设备对象 */
struct cdev *cdev_alloc(void); /* 初始化cdev设备对象 */
void cdev_init(struct cdev*, const struct file_opeartions*);