「深入浅出:Linux字符设备号解析」 (linux 字符设备号)
深入浅出:Linux字符设备号解析
在Linux系统中,设备文件可分为两种类型:块设备和字符设备。其中字符设备,是一种能够一次性读写一个字节或一个字符的设备,如键盘、鼠标、打印机、声卡等。而字符设备号,则用于在Linux系统中唯一标识每个字符设备。本篇文章将深入浅出地解析Linux字符设备号的相关知识。
Linux字符设备号的定义
在Linux系统中,每个字符设备号由两部分组成:主设备号和次设备号。主设备号用于标识设备所属的设备类型,同时也决定了字符设备的主要操作函数;而次设备号则用于标识同一类型设备的不同实例。
一般情况下,主设备号的值是预设的,而次设备号则由内核动态分配。在Linux源码的include/linux/major.h中,我们可以找到一些已经预设好的主设备号,如下所示:
“`
#define MEM_MAJOR 1
#define FLOPPY_MAJOR 2
#define HD_MAJOR 3
#define TTY_MAJOR 4
#define LP_MAJOR 6
“`
其中,4号主设备号的被称为tty设备,即终端设备,这是Linux中最常见的设备类型。其他设备类型如网络设备、声卡、输入设备等,都有自己的主设备号。
次设备号的分配
Linux内核用一套动态分配的方式来为字符设备分配次设备号。这一套机制叫做udev(user space device),是内核态和用户态之间交互的重要组成部分。
当我们插入一台新设备时,udev会首先查询目录/lib/udev/devices,找到一个未使用的次设备号,然后创建一个对应的设备文件,最终将该设备文件与对应的次设备号关联。这样,在用户态通过设备文件访问到设备时,实际上是通过该文件与次设备号关联起来的。
此外,次设备号的分配方式还可以通过内核态ioctl接口进行配置。在实际开发中,我们可以通过下面这段代码来修改设备的次设备号
“`
int ioctl(int fd, unsigned long cmd, unsigned long arg);
“`
其中fd是打开设备文件返回的文件描述符,cmd是需要执行的命令,arg是与命令有关的参数。通过这个接口,我们可以动态分配和修改次设备号,实现更精细的设备管理和控制。
Linux字符设备号的使用
有了主次设备号,我们就可以构造字符设备号了。在Linux内核的include/linux/fs.h中,有一个宏MKDEV,可以用于将主次设备号合并成一个字符设备号。例如:
“`
dev_t devno = MKDEV(2, 1); // devno此时为 0x0201
“`
其中,2表示主设备号,1表示次设备号。需要注意的是,主次设备号的更大取值都为255,在分配前需要充分考虑到主设备号的预设值。
除了MKDEV宏,我们还可以通过字符设备相关头文件的宏定义来获取主设备号或次设备号。
其中,MAJOR宏返回设备号的主设备号,MINOR宏返回设备号的次设备号。我们也可以用来这样直接获取设备号
“`
dev_t devno;
devno = inode->i_rdev; // 获取设备号
unsigned int major = MAJOR(devno);
unsigned int minor = MINOR(devno);
“`
其中,inode是一个Linux内核中的数据结构,表示一个文件的i-node节点。通过i-node节点,我们可以访问到文件的各项属性,包括文件所关联的设备文件。i_rdev即是i-node节点中的设备号信息。
在Linux系统中,字符设备是一种能够一次性读写一个字节或一个字符的设备,如键盘、鼠标、打印机、声卡等。字符设备号则用于在Linux系统中唯一标识每个字符设备。
字符设备号由两部分组成:主设备号和次设备号。其中,主设备号用于标识设备所属的设备类型,次设备号则用于标识同一类型设备的不同实例。主设备号的值是预设的,而次设备号则由内核动态分配。
通过MKDEV宏、MAJOR宏和MINOR宏等宏定义,我们可以方便地获取和操作字符设备号。同时,通过ioctl接口,我们还可以动态分配和修改次设备号,实现更精细的设备管理和控制。