学无止境-Linux-申请设备号注意事项

备注:学习记录所用,若有高手不吝赐教,万分感谢!

申请设备号过程现在基本都是如下:

#define N_DEVS_MINOR		32

if(major) {
		devno = MKDEV(major, 0);
		ret = register_chrdev_region(devno, N_DEVS_MINOR, DEV_NAME);
	}
	else{
		ret = alloc_chrdev_region(&devno, 0, N_DEVS_MINOR, DEV_NAME);
		major = MAJOR(devno);
		minor = MINOR(devno);
	}
    if (ret)
		goto fail_chrdev;

网上对于设备号的解释也基本如下:设备号分为主设备号和次设备号。其中主设备号是用来区分不同类别的设备,而次设备号用来区分一类设备中的不同个体。

需要注意的是:以上的申请过程掺杂有次设备号在里面,所以容易忽视“同类别设备”和“个体设备”的区分;上面代码申请的设备号实际上主要是“用来区分不同类别的设备”。

而想要为同一类别设备的不同个体申请设备号,则应该按以下流程:

    1、按照上面的代码申请一个设备号(也可以直接当作:同类设备的第一个个体的设备号)。

         个人理解这一步主要是用来申请“主设备号”,也就是用来区分设备的类别,此处的DEV_NAME也应该是设备类别名(如:spi),而不是个体设备名(如:spi0、spi1)。

         申请完成后应该将主设备号:major = MAJOR(devno);记录下来,以供为其他不同个体申请设备号时使用。

    2、为其他不同个体申请设备号:

/*为一类设备申请设备号“空间”,
假如这一类设备一共可以有32个不同的个体*/
#define N_DEVS_MINOR		32
static DECLARE_BITMAP(minors, N_DEVS_MINOR); 

/*从“空间”中为个体申请一个子设备号*/
minor = find_first_zero_bit(minors, N_DEVS_MINOR);
/*这里的主设备号,就是从第一步申请的设备号中获取出来的*/
devno = MKDEV(major, minor);

再做其他过程,如:
err = cdev_add(&cdev, devno, N_DEVS_MINOR);
dev = device_create(class, NULL, devno, NULL, name);

/*设备注册完成之后,将已经申请的个体子设备号“锁住”,
 申请主设备号(也是第一个设备的主次设备号)时,是否要锁子设备号待验证*/
set_bit(minor, minors);

所以可以这么写:

#define N_DEVS_MINOR		32
static DECLARE_BITMAP(minors, N_DEVS_MINOR);

/*也可以直接给定一个值,
先“cat /proc/devices”查看当前有哪些已经被申请的设备号,
避免冲突*/
int major = 0;

void func_register_devt()
{
    if(major) {
        devno = MKDEV(major, 0);
        ret = register_chrdev_region(devno, N_DEVS_MINOR, DEV_NAME);
    }
    else{
        ret = alloc_chrdev_region(&devno, 0, N_DEVS_MINOR, DEV_NAME);
        major = MAJOR(devno);
        //minor = MINOR(devno); 个人认为没必要记录
    }
    if (ret)
        goto fail_chrdev;
}

void func_register_spi_device(char *name, int id)
{
    int minor = 0;
    dev_t devno = 0;
 
    minor = find_first_zero_bit(minors, N_DEVS_MINOR);
    devno = MKDEV(major, minor);
    sprintf(name, "spi-%d", id);

    ……
    cdev_add(&cdev, devno, N_DEVS_MINOR);
    dev = device_create(class, NULL, devno, NULL, name);
    ……

    set_bit(minor, minors);
    
    ……
}

 设备号申请函数调用一次即可。

 这只是一种代码格式,只要保证申请主设备号的过程只执行一次就行。

注:设备号充足的情况下,为每个个体都单独申请一个主设备号也没事。

posted @ 2025-01-02 20:03  xMofang  阅读(49)  评论(0)    收藏  举报