register_chrdev深入分析

来源:互联网 发布:linux启动服务的命令 编辑:程序博客网 时间:2024/06/08 06:09

 
register_chrdev
      __register_chrdev(major, 0, 256, name, fops);
            struct char_device_struct *cd;
            cd = __register_chrdev_region(major, baseminor, count, name);
                    cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
                    //如果主设备号是0的话,就会从char_device_struct数组中选择一个没有分配的char_device_struct结构体
                    //如果找到的话,就以其下标作为主设备号,否则出错返回
                    cd->major = major;
                    cd->baseminor = baseminor;//第一个次设备号
                    cd->minorct = minorct;         //此设备号的个数
                    strlcpy(cd->name, name, sizeof(cd->name));//设置名字
                    i = major_to_index(major);
                          return major % CHRDEV_MAJOR_HASH_SIZE;//只有当指定的主设备号大于255时,i才会不等于major
                   //下面的工作比较难懂,可以参考注释1
            cdev = cdev_alloc(); //分配字符设备结构体
            cdev->owner = fops->owner; //设置字符设备结构体
            cdev->ops = fops;
            kobject_set_name(&cdev->kobj, "%s", name);
            //向上注册,这里用到了cd->major和baseminor
            err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
            
之前我们编写字符设备驱动程序只是一个register_chrdev来完成,通过我们将这个函数分解开来就看出来了,如果使用register_chrdev的话,不能指定此设备号,那么就会默认baseminor=0,count=256。这就造成了浪费!因为一个主设备号下的所有此设备号都只能对应同一个字符设备!如果我们使用__register_chrdev_region的话,情况就变了,我们可以指定baseminor和count,这样就可以让一个主设备号下每一个次设备号都对应字节的字符设备了!

注释1:
我们用个例子来说明__register_chrdev_region做了什么:
比如我们先注册了3个字符设备,主设备号都是2,次设备号分别是0、1~2、3,那么经过__register_chrdev_region这个函数就会形成下面的链表:

register_chrdev深入分析 - 小白 - 小白的博客
 
注意:不好意思,这边有个小错误,那就是主设备号不能是0,要从1开始,而不是0!

如果此时如果再想注册一个字符设备,它的主设备号是257,此设备号是0,那么会形成如下链表:

 register_chrdev深入分析 - 小白 - 小白的博客

这里面有两点是很重要的:
第一:chrdevs的每一项并不是只对应一个与其下表相同的主设备号,而是对应一系列主设备号,这些主设备号=“chrdevs下表+n*255”!
第二:chrdevs的每一项主设备号相同的字符设备此设备号不能有交集,主设备号不同的字符设备此设备号可以有交集!

从而我们也看到了__register_chrdev_region这个函数的功能,其实它也是实现一个互斥访问的功能!