1:register_chrdev_region
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
int
register_chrdev_region(dev_t from, unsigned count,
const
char
*name)
{
struct
char_device_struct *cd;
dev_t to = from + count;
dev_t n, next;
for
(n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if
(next > to)
next = to;
cd = __register_chrdev_region(MAJOR(n), MINOR(n),
next - n, name);
if
(IS_ERR(cd))
goto
fail;
}
return
0;
fail:
to = n;
for
(n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
return
PTR_ERR(cd);
}
|
register_chrdev_region函数和register_chrdev函数类似,也是用于字符设备驱动的注册,不同点在于register_chrdev函数在注册字符设备驱动的时候是一步完成的,而register_chrdev_region函数在注册字符设备驱动的时候是分两步完成的:
第一步:注册/分配主次设备号
第二步:注册字符设备驱动
此外有register_chrdev_region函数的源码可以发现,register_chrdev_region可以同时注册多个设备号
2:cdev结构体的定义
1
2
3
4
5
6
7
8
|
struct
cdev {
struct
kobject kobj;
//每个cdev都是一个kobject
struct
module *owner;
//指向实现驱动的模块
const
struct
file_operations *ops;
//操作这个字符设备的方法
struct
list_head list;
//与cdev对应的字符设备文件的inode->i_devices的链表头
dev_t dev;
//起始的设备号
unsigned
int
count;
//设备号的范围,也可以用于计数等,起始就是一个普通的变量
};
|
cdev结构体的定义在linux/cdev.h中,这个结构体的定义是用于描述一个设备驱动
注册函数相关的函数
cdev_alloc:给cdev结构体分配内存(指针实例化)
cdev_init:绑定cdev和file_operations
cdev_add:注册设备
cdev_del:注销设备
3:dev_t类型
dev_t类型其本质就是一个unsigned int 类型的变量,这个变量用于存放主次设备号,比如高16位存放主设备号,低16位存放次设备号,具体哪些位用来存放主设备号,哪些位用来存放次设备号要看具体的定义。
4:设备号相关的三个宏
MKDEV:由主次设备号换算得到一个设备号
1
2
3
|
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
ma:主设备号
mi:次设备号
|
MAJOR:从设备号中取出主设备号
1
|
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
|
MINOR:从设备号中取出次设备号
1
|
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
|
本文转自 菜鸟养成记 51CTO博客,原文链接:http://blog.51cto.com/11674570/1872435