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`目录下创建节点。切记,除嵌入式系统且完全掌控设备树的特殊情况外,千万不要硬编码主设备号,并且卸载驱动时务必释放设备号,防止泄漏。