第四节、杂项设备驱动
本节用于介绍杂项设备驱动
Linux三大设备驱动
- 字符设备:IO的传输过程是以字符为单位的,没有缓冲。比如l2C,SPl都是字符设备
- 块设备:IO的传输过程是以块为单位的。根存储相关的,都属于块设备,比如,f卡
- 网络设备:与前俩个不一样,是以socket套接字来访问的。
1、我们这节课要讲的杂项设备驱动是属于我们这三大设备驱动里面的哪个呢?
杂项设备是字符设备的一种。可以自动生成设备节点。
我们的系统里面有很多杂项设备。我们可以输入cat/proc/misc命令来查看。
2、杂项设备除了比字符设备代码简单,还有别的区别吗?
杂项设备的主设备号是相同的,均为10,次设备号是不同的。主设设备号相同就可以节省内核的资源。
3、主设备号和次设备号是什么?
设备号包含主设备号和次设备号,主设备号在Linux系统里面是唯一的,次设备号不一定唯一。
设备号是计算机识别设备的一种方式,主设备相同的就被视为同一类设备
主设备号可以通过命令 cat/proc/devices来查看。
4、杂项设备的接口结构体定义
文件位置:include/linux/miscdevice.h
struct miscdevice {
int minor; //次设备号
const char *name; //设备的名字,/dev路径下产生的节点的名字
const struct file_operations *fops; //文件操作集
struct list_head list;
struct device *parent;
struct device *this_device;
const struct attribute_group **groups;
const char *nodename;
umode_t mode;
};
其中,主设备号相同的不同设备的次设备号不能有一样的
#define MISC_DYNAMIC_MINOR 255
这个宏定义MISC_DYNAMIC_MINOR可以自动分配次设备号
注册杂项设备和注销杂项设备的函数
extern int misc_register(struct miscdevice *misc);
extern void misc_deregister(struct miscdevice *misc);
5、文件操作集结构体定义
文件位置:include/linux/fs.h
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 (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
int (*iterate_shared) (struct file *, struct dir_context *);
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 *);
...
};
里面的一个结构体成员对应一个调用
6、注册杂项设备的流程
- 填充miscdevice结构体
- 填充file_operations结构体
- 注册杂项设备并生生成设备节点
struct file_operations xx_fops = {
.owner = THIS_MODULE
...
};
struct miscdevice xx_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "xxx",
.fops = &xx_fops
}
static int xxx_init()
{
int ret;
ret = misc_register(&xx_dev);
if(ret<0)
{
printk("misc register error\n");
return -1;
}
return 0;
}
void xxx_exit()
{
misc_deregister(&xx_dev);
}