Linux字符设备号

一.  简介

为了方便管理,Linux 中每个设备都有一个设备号。

为了后面字符设备驱动的学习,本文了解一下 设备号组成与分配。

二.  Linux字符设备号的组成与分配

1.  设备号的组成

设备号由主设备号和次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备。

一个名为 dev_t 的数据类型表示设备号,dev_t 定义在文件 include/linux/types.h 里面,通过 vscode软件可以打开(NXP官方提供的) Linux内核源码,输入 "Ctrl+p" 组合键即可搜索 types.h。

dev_t 数据类型定义如下:

typedef __kernel_dev_t		dev_t;
.............
typedef __kernel_dev_t      dev_t;

可以看出 dev_t 是__u32 类型的,而__u32 定义在文件 include/uapi/asm-generic/int-ll64.h 里面,定义如下:

typedef unsigned int __u32;

Linux内核将设备号分为两部分:主设备号和次设备号。主设备号占用前12位,次设备号占用低20位。综上所述,dev_t  就是 unsigned int 类型,即为一个 32 位的数据类型。这 32 位的数据构成了主设备号和次设备号两部分,其中高 12 位为主设备号,低 20 位为次设备号。

因此, Linux 系统中主设备号范围为 0~4095,所以大家在选择主设备号的时候一定不要超过这个范围。

在文件 include/linux/kdev_t.h 中提供了几个关于设备号的操作函数(本质是宏),如下所示:

#define MINORBITS	20
#define MINORMASK	((1U << MINORBITS) - 1)

#define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))

以上几个宏可以看出,从 dev_t 获取主设备号和次设备号,MAJOR(dev_t)函数,或MINOR(dev_t)函数。也可以使用主设备号和次设备号构成 dev_t,调用MKDEV(major,minor)函数即可。

2.  设备号的分配

(1)静态分配设备号

前面讲解字符设备驱动的时候说过了,注 册字符设备的时候需要给设备指定一个设备号,这个设备号可以是驱动开发者静态的指定一个 设备号,例如,选择 200 这个主设备号。有一些常用的设备号已经被 Linux 内核开发者给分配掉 了,具体分配的内容可以查看文档 Documentation/devices.txt
并不是说内核开发者已经分配掉 的主设备号我们就不能用了,具体能不能用还得看我们的硬件平台运行过程中有没有使用这个 主设备号,使用“ cat /proc/devices ”命令即可查看当前系统中所有已经使用了的设备号。

(2)动态分配设备号

静态分配设备号需要我们检查当前系统中所有被使用了的设备号,然后挑选一个没有使用 的。 而且静态分配设备号很容易带来冲突问题。
Linux 社区推荐使用动态分配设备号,在注册字符设备之前先申请一个设备号,系统会自动给你一个没有被使用的设备号,这样就避免了冲突。 卸载驱动的时候释放掉这个设备号即可。
设备号的申请函数如下:

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

函数 alloc_chrdev_region 用于申请设备号,此函数有 4 个参数:

dev :保存申请到的设备号。
baseminor 次设备号起始地址, alloc_chrdev_region 可以申请一段连续的多个设备号,这些设备号的主设备号一样,但是次设备号不同,次设备号以 baseminor 为起始地址地址开始递 增。一般 baseminor 0 ,也就是说次设备号从 0 开始。
count 要申请的设备号数量。
name :设备名字。

注销字符设备之后要释放掉设备号,设备号释放函数如下:
void unregister_chrdev_region(dev_t from, unsigned count)
此函数有两个参数:
from :要释放的设备号。
count 表示从 from 开始,要释放的设备号数量。

注意:Linux 给每一个设备分配了一个设备号,所以,在写驱动时我们要保证设备的主设备号与次设备号都是唯一的。绝不能与现有的设备的设备号冲突!!!

你可能感兴趣的:(linux,运维,服务器)