一个主设备号是如何支持多个次设备?
Posted 正在起飞的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个主设备号是如何支持多个次设备?相关的知识,希望对你有一定的参考价值。
1、主次设备号
2、次设备号介绍
(1)在老的驱动程序里是不需要次设备号的,在老版内核中注册驱动用register_chrdev()函数,只需要传入主设备号,次设备号默认是0;
(2)后面的驱动注册函数,需要通过alloc_chrdev_region()函数先申请设备号,其中就包括第一个设备号和次设备号的个数;
(3)主设备号和次设备号共同表示一个设备驱动;
3、使用次设备号的好处
(1)共享主设备号的驱动程序一般都是一类设备,这样方便管理和理解;
(2)某些时候不同的设备是可以共享同一个驱动程序,只需要在驱动程序中对次设备进行区分,这样多个设备就只占用一个主设备号;比如串口驱动,不同的串口操作方法都是一样的,不一样的是串口对应的寄存器基地址,如果我们能在驱动程序中通过次设备号知道此次是操作哪个串口,然后就使用对应的寄存器基地址,就可以实现多个串口共用一个驱动程序;
(3)多个设备共享一个主设备号,通过次设备号区分,可以节省主设备号。在内核中,字符设备驱动都注册到chrdevs全局变量中,这是一个结构体指针数组,总共有255个成员,也就是说内核最多支持255个字符设备驱动;
4、驱动程序如何区分次设备号
4.1、创建设备节点
(1)创建设备节点会指定主次设备号,通过主次设备号就可以找到对应的驱动程序;
(2)(参考博客:《字符设备驱动程序自动创建设备节点详解》和《设备节点如何与设备驱动关联》;
4.2、上层应用程序打开设备节点
//驱动代码中struct file_operations结构体的open函数指针
int open(struct inode *, struct file *)
//将描述字符设备的struct cdev结构体传给struct file结构体,后续操作会用到
file->private_data = inode->i_cdev;
return 0;
(1)在创建设备节点时指定了主次设备号,所以open函数打开设备节点时,struct inode结构体中就报错了主次设备号和对应的struct cedv结构体指针;
(2)只有在open设备节点时才会传入struct inode结构体指针和struct file结构体指针,但是在struct file结构体指针中时不包含主次设备号信息的;
(3)struct file结构体中有个private_data 变量,时专门用来存私有数据的,我们可以在open打开时将主次设备号保存到private_data 变量中;
4.3、应用程序读写驱动程序
//驱动代码中struct file_operations结构体的read函数指针
ssize_t read(struct file *file, char __user *buf, size_t size, loff_t *pos)
struct cdev *cd;
unsigned int minor;
//得到open函数打开设备节点时保存的数据
cd = (struct cdev *)file->private_data;
//获得次设备号
minor = MINOR(cd->dev)
//根据不同的次设备进行操作
······
return size;
(1)应用程序在调用read、write等操作驱动程序函数时,都会把struct file结构体传入,在open时我们已经把字符设备驱动的相关信息保存到struct file结构体的private_data中;
(2)在操作前去解析struct file结构体的private_data变量,得到次设备号,有了次设备号后续就可以进行差别的操作;
补充:上面只介绍了read函数,但是其他的操作函数也是一样的,都会传入struct file结构体指针;
以上是关于一个主设备号是如何支持多个次设备?的主要内容,如果未能解决你的问题,请参考以下文章