Linux驱动|你确定你真的搞懂字符设备号的管理?
一、Linux内核字符设备号每一个字符设备都需要设备号Linux内核通过字符设备号来区分设备的唯一标识。设备号由主设备号(major)次设备号(minor)组成。主设备号关联到具体的驱动程序如1对应mem5对应tty。次设备号区分同一驱动管理的多个设备。操作依赖设备号以下是常用的设备号操作函数配套使用函数功能原型MKDEV(major, minor)由主 / 次设备号生成dev_tdev_t MKDEV(unsigned int major, unsigned int minor);MAJOR(dev)从dev_t提取主设备号unsigned int MAJOR(dev_t dev);MINOR(dev)从dev_t提取次设备号unsigned int MINOR(dev_t dev);宏定义位于内核文件include/linux/kdev_t.h7#define MINORBITS208#defineMINORMASK((1UMINORBITS)-1)910#defineMAJOR(dev)((unsignedint)((dev)MINORBITS))11#defineMINOR(dev)((unsignedint)((dev)MINORMASK))12#defineMKDEV(ma,mi)(((ma)MINORBITS)|(mi))主次设备号内存组成如下Linux内核提供的主要注册字符设备函数register_chrdev()、register_chrdev_region()。二、 Linux内核字符设备号管理规则Linux内核字符设备号管理规则数组**chrdevs[CHRDEV_MAJOR_HASH_SIZE]**维护所有的字符设备主次设备号主设备号值区间[0 512]数组下标与主设备号值关系小于255的主设备号值等于下标大于254小于512的主设备号对255取余后的值等于小标(比如主设备号251和506共用同一个下标)每一个主设备号(251和506虽然公用同一个数组下标但是各自对应2^20个次设备号)对应的次设备号区间[0-1048575]次设备号可以分块申请块内次设备号必须连续各个块之间的次设备号不能重叠每一块次设备号由结构体struct char_device_struct表示按照次设备号从小到大顺序通过链表将各个次设备号块连接起来三、实例代码验证为方便验证代码彭老师从内核中将字符设备号申请注册的核心代码单独拎出来去掉一些内核特定函数这样我们可以脱离内核进行测试:四、测试我们通过一组实例讲解字符设备号的分配register_chrdev_region(MKDEV(251,0),3,cdev1); /* 1 */ register_chrdev_region(MKDEV(251,3),4,cdev2); /* 2 */ register_chrdev_region(MKDEV(506,0),3,cdev3); /* 3 */ register_chrdev_region(MKDEV(506,3),4,cdev4); /* 4 */ register_chrdev(234,cdevA); /* 5 */ register_chrdev(489,cdevB); /* 6 */申请字符设备chardev1主设备号251次设备号基值0、个数3、区间[0-2]申请字符设备chardev2主设备号251次设备号基值3、个数4、区间[3-6]申请字符设备chardev3主设备号506次设备号基值0、个数3、区间[0-2]申请字符设备chardev4主设备号506次设备号基值3、个数4、区间[3-6]申请字符设备chardevA主设备号234次设备号区间[0-255]申请字符设备chardevB主设备号489次设备号区间[0-255]申请成功之后节点信息如下如果此时我们要再申请字符设备cdev5register_chrdev_region(MKDEV(506,4),4,cdev5);主设备号506次设备号基值4、个数4、区间[4-7]那么就会和字符设备cdev4冲突从而申请失败。五、代码获取完整代码获取关注添加好友或者后台回复charno