Linux设备号
.1设备号的构成
在Linux系统里,每个设备都有专属的设备号,这是系统高效管理设备的关键。设备号由主设备号和次设备号共同组成:主设备号精准定位某一类特定的驱动,而次设备号则精准区分使用同一驱动的不同设备。
Linux内核专门定义了dev_t数据类型来表示设备号,其定义位于include/linux/types.h文件中,实质是unsigned int类型的无符号32位数据。这32位数据里,高12位担当主设备号,低20位则为次设备号。如此一来,主设备号的取值范围限定在0~4095,我们在设定主设备号时,必须严格遵循这个范围。
在include/linux/kdev_t.h文件中,提供了几个操作设备号的实用宏函数:
-
MINORBITS宏明确次设备号占20位; -
MINORMASK是次设备号的掩码; -
MAJOR宏通过将dev_t右移20位,轻松获取主设备号;
-
MINOR宏借助取dev_t低20位,精准获取次设备号; -
MKDEV宏可以把给定的主设备号和次设备号,巧妙组合成dev_t类型的设备号。
.2设备号的分配
1.静态分配设备号
这里所讲的设备号分配,主要聚焦于主设备号。注册字符设备时,必须给设备指定设备号,开发者可以采用静态方式指定,例如选定200作为主设备号。
不过,Linux内核开发者已经预先分配了一些常用设备号,详细情况可查阅Documentation/devices.txt文档。但这并不意味着这些主设备号就绝对不能使用,关键要看硬件平台运行时是否占用了该设备号。通过执行“cat /proc/devices”命令,就能查看当前系统已经使用的设备号。
2.动态分配设备号
静态分配设备号,要求开发者逐一排查系统已用设备号,从中挑选未被使用的,极易引发冲突。因此,Linux社区强烈推荐使用动态分配设备号。在注册字符设备前,先向系统申请设备号,系统会自动分配一个未被使用的,从根源上避免冲突。卸载驱动时,释放设备号即可。
申请设备号的函数是alloc_chrdev_region(),参数含义如下:
-
dev:用于存储申请到的设备号; -
baseminor:次设备号起始地址,该函数可申请连续多个设备号,这些设备号主设备号相同,次设备号以baseminor为起点递增,通常设为0,即次设备号从0开始;
-
count:申请设备号的数量; -
name:设备名称。
注销字符设备后,要使用unregister_chrdev_region()释放设备号,参数说明如下:
-
from:需要释放的设备号; -
count:从from开始,释放设备号的数量。
开发建议:
实际开发时,优先采用alloc_chrdev_region()进行动态分配。驱动加载后,能借助“cat /proc/devices | grep your_driver_name”获取实际设备号。
对于设备节点创建,桌面和服务器系统可利用udev规则,也可在驱动中借助class_create()和device_create(),自动在/dev目录下创建节点。切记,除嵌入式系统且完全掌控设备树的特殊情况外,千万不要硬编码主设备号,并且卸载驱动时务必释放设备号,防止泄漏。