4.4.1.1. 设备号的申请和归还¶
Linux内核提供了两种方式来定义字符设备,如下所示。
定义字符设备¶
1
2
3
4//第一种方式
static struct cdev chrdev;
//第二种方式
struct cdev *cdev_alloc(void);
第一种方式,就是我们常见的变量定义;第二种方式,是内核提供的动态分配方式,调用该函数之
后,会返回一个struct cdev类型的指针,用于描述字符设备。
从内核中移除某个字符设备,则需要调用cdev_del函数,如下所示。
cdev_del函数¶
1void cdev_del(struct cdev *p)
函数参数和返回值如下:
参数:
p: 该函数需要将我们的字符设备结构体的地址作为实参传递进去,就可以从内核中移除该字符设备了。
返回值: 无
register_chrdev_region函数
register_chrdev_region函数用于静态地为一个字符设备申请一个或多个设备编号。函数原型如下所示。
register_chrdev_region函数¶
1int register_chrdev_region(dev_t from, unsigned count, const char *name)
函数参数和返回值如下:
参数:
from:dev_t类型的变量,用于指定字符设备的起始设备号,如果要注册的设备号已经被其他的设备注册了,那么就会导致注册失败。
count:指定要申请的设备号个数,count的值不可以太大,否则会与下一个主设备号重叠。
name:用于指定该设备的名称,我们可以在/proc/devices中看到该设备。
返回值: 返回0表示申请成功,失败则返回错误码
alloc_chrdev_region函数
使用register_chrdev_region函数时,都需要去查阅内核源码的Documentation/devices.txt文件,
这就十分不方便。因此,内核又为我们提供了一种能够动态分配设备编号的方式:alloc_chrdev_region。
调用alloc_chrdev_region函数,内核会自动分配给我们一个尚未使用的主设备号。
我们可以通过命令“cat /proc/devices”查询内核分配的主设备号。
alloc_chrdev_region函数原型¶
1int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
函数参数和返回值如下:
参数:
dev:指向dev_t类型数据的指针变量,用于存放分配到的设备编号的起始值;
baseminor:次设备号的起始值,通常情况下,设置为0;
count、name:同register_chrdev_region类型,用于指定需要分配的设备编号的个数以及设备的名称。
返回值: 返回0表示申请成功,失败则返回错误码
unregister_chrdev_region函数
当我们删除字符设备时候,我们需要把分配的设备编号交还给内核,对于使用register_chrdev_region函数
以及alloc_chrdev_region函数分配得到的设备编号,可以使用unregister_chrdev_region函数实现该功能。
unregister_chrdev_region函数(内核源码/fs/char_dev.c)¶
1void unregister_chrdev_region(dev_t from, unsigned count)
函数参数和返回值如下:
参数:
from:指定需要注销的字符设备的设备编号起始值,我们一般将定义的dev_t变量作为实参。
count:指定需要注销的字符设备编号的个数,该值应与申请函数的count值相等,通常采用宏定义进行管理。
返回值: 无
register_chrdev函数
除了上述的两种,内核还提供了register_chrdev函数用于分配设备号。该函数是一个内联函数,它不
仅支持静态申请设备号,也支持动态申请设备号,并将主设备号返回,函数原型如下所示。
register_chrdev函数原型(内核源码/include/linux/fs.h文件)¶
1
2
3
4
5static inline int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
{
return __register_chrdev(major, 0, 256, name, fops);
}
函数参数和返回值如下:
参数:
major:用于指定要申请的字符设备的主设备号,等价于register_chrdev_region函数,当设置为0时,内核会自动分配一个未使用的主设备号。
name:用于指定字符设备的名称
fops:用于操作该设备的函数接口指针。
返回值: 主设备号
我们从以上代码中可以看到,使用register_chrdev函数向内核申请设备号,同一类字
符设备(即主设备号相同),会在内核中申请了256个,通常情况下,我们不需要用到这么多个设备,这就造成了极大的资源浪费。
unregister_chrdev函数
使用register函数申请的设备号,则应该使用unregister_chrdev函数进行注销。
unregister_chrdev函数(内核源码/include/linux/fs.h)¶
1
2
3
4static inline void unregister_chrdev(unsigned int major, const char *name)
{
__unregister_chrdev(major, 0, 256, name);
}
函数参数和返回值如下:
参数:
major:指定需要释放的字符设备的主设备号,一般使用register_chrdev函数的返回值作为实参。
name:执行需要释放的字符设备的名称。
返回值: 无