Linux驱动开发之设备号

2021-07-06

关键字:主设备号、次设备号


 

1、什么是设备号

设备号是Linux驱动开发中的术语。

 

Linux规定每一个字符设备或块设备都必须拥有一个专属设备号。要想在Linux平台开发驱动程序,申请设备号就是开发过程的第一步,只有有了设备号,才能向系统注册设备。

 

一个设备号由以下两个模块组成:

1、主设备号;

2、次设备号;

 

主设备号用以表示一个驱动程序的种类。如:USB、显示器、鼠标等。

 

次设备号用以表示此种类下具体的设备。如:第n个USB接口、第n个显示屏、第n个鼠标等。

 

主设备号是抽象的事物种类,次设备号则是具象的实体设备。

 

在 /proc/devices 文件中记载着系统中所有已注册的主设备号及其注册名称。

 

设备号占32位的宽度。其中主设备号占高12位,次设备号占低20位。不过虽然主设备号的宽度长达12位,实际上在Linux系统中有效值范围仅为 1 ~ 255。

 

 

2、设备号相关的接口

虽然我们知道主设备号和次设备号的具体位置,但是还是应该以系统提供的接口来拆分和组合主次设备号。

 

在Linux内核中,设备号被描述为 dev_t 类型,如下所示:

typedef u_long dev_t;

这个类型的定义隐藏的很深,不必去纠结它的实际定义头文件。我们在开发驱动过程中只需要引入kdev_t.h头文件就可以使用此类型的了:

./kernel/include/linux/kdev_t.h

 

同时,kdev_t.h头文件中还定义了拆分和组合主次设备号的,简要概括如下:

MAJOR(dev_t) //从设备号中将主设备号拆分出来
MINOR(dev_t) //从设备号中将次设备号拆分出来

MKDEV(major, minor) //将主设备号和次设备号组合成设备号

 

 

3、静态注册

第1节有提到过:必须持有设备号才能向系统注册设备。而设备号是一个整数,所以理论上我们可以随意“捏造”一个设备号用以向系统注册我们的设备。这种“捏造”设备号以注册设备的形式就被称为“静态注册”方式。

 

不过这里有一个前提条件:尽量不要和已有的设备号冲突,否则可能会导致设备工作不正常。一般可以在内核源码的 documentation/devices.txt 中看到所有已被注册使用的设备号,我们按需选择一个没被占用的即可。不过如果我们要添加的设备的种类就是系统中已有的种类,那一般我们只需要注册次设备号不要冲突就可以了。

 

静态注册的方式需要注意的点太多,徒增开发难度。因此应尽量使用动态注册的形式。

 

 

4、动态注册

Linux有提供一个动态分配设备号的接口,其原型如下所示:

int alloc_chrdev_region(dev_t* devid, unsigned int baseminor, unsigned int count, const char* name);

参数 devid 作为输出参数使用。

参数 baseminor 表示次设备号起始值。按需设置即可。

参数 count 表示要申请使用的次设备号的数量。

参数 name 表示此设备的描述名称,即在 /proc/devices 中看到的名称。

返回值0表示申请成功。

 

与动态注册相对的是释放接口。Linux中的设备号是交由系统托管的。如果某驱动程序在运行过程中动态申请了某设备号,但是在卸载时没有释放,则该设备号仍旧存活于系统中。释放设备号的接口原型如下所示:

void unregister_chrdev_region(dev_t devid, unsigned int count);

参数 devid 表示设备号。

参数 count 即次设备号数量。

 


 

posted @ 2021-07-06 22:54  大窟窿  阅读(946)  评论(0编辑  收藏  举报