主、次编号是否唯一

主、次编号是否唯一

号码是major, minor唯一的吗?

我们有任何引用和参考吗?

NAME   MAJ:MIN RM   SIZE RO MOUNTPOINT
sda      8:0    0 465.8G  0 
├─sda1   8:1    0 298.2M  0 
├─sda2   8:2    0     3G  0 
├─sda3   8:3    0 458.7G  0 /
├─sda4   8:4    0     1K  0 
└─sda5   8:5    0   3.8G  0 
sr0     11:0    1  1024M  0 

答案1

Linux 编程接口,§14.1

每个设备文件都有一个主ID号和一个次ID号。主 ID 标识设备的一般类别,内核使用它来查找此类设备的适当驱动程序。次要 ID 唯一标识通用类别中的特定设备。设备文件的主要 ID 和次要 ID 通过 ls -l 命令显示。

[...]

每个设备驱动程序都注册其与特定主设备ID的关联,并且该关联提供了设备专用文件和设备之间的连接。当内核查找设备驱动程序时,设备文件的名称无关紧要。

另请参阅旧版 (2001)Linux 设备驱动程序(2e) 章

即,目的是为每种类型的设备提供主要:次要到设备:实例的唯一映射。严格来说,你有两个不同的设备,具有相同的主要:次要,只要一个是字符,一个是块:

# ls -l /dev/ram1 /dev/mem
crw-r----- 1 root kmem 1, 1 Jan  1  1970 /dev/mem
brw-rw---- 1 root disk 1, 1 Jan  1  1970 /dev/ram1

在 Linux 上,在一个系统上的任何时间点主要:次要数字对于每种类型的设备是独一无二的。然而,这些数字可能会随着时间的推移而变化,并且在不同的 Linux 系统上(即使是相同的发行版、内核和硬件)不必相同。请注意,字符设备和块设备具有不同的编号空间,例如,块主设备 1 分配给 RAM 磁盘,字符主设备 1 分配给一组内核设备(包括 null 和零)。

历史上设备专业是(大部分)静态地分配通过一个注册表(虽然没有维护,但仍然存在于内核源代码中Documentation/devices.txt)。如今,许多设备都是动态分配的,这是由乌德夫,以及可在 中查看的映射/proc/devices。固定设备仍然存在incude/uapi/linux/major.h(最近搬自include/major.h

现在,虽然主要:次要组合唯一标识特定的设备实例,但没有什么可以阻止您创建引用同一设备的多个设备节点(文件)。它们甚至不必创建/dev(但它们必须位于支持创建设备节点的文件系统上,并且不使用该nodev选项安装)。

常见用途是在 chroot 中创建重复的零、空和随机设备:

# find /dev /var/chroot -regextype posix-extended -regex ".*/(zero|null|random)" -type c | 
xargs ls -l
crwxrwxrwx 1 root root 1, 3 2012-11-21 03:22 /dev/null
crw-rw-r-- 1 root root 1, 8 2012-05-07 10:35 /dev/random
crw-rw-rw- 1 root root 1, 5 2012-11-21 03:22 /dev/zero
crwxrwxrwx 1 root root 1, 3 2012-11-21 03:22 /var/chroot/sendmail/dev/null
crw-rw-r-- 1 root root 1, 8 2012-05-07 10:35 /var/chroot/sendmail/dev/random
crw-rw-rw- 1 root root 1, 5 2012-11-21 03:22 /var/chroot/sendmail/dev/zero

名称只是别名,内核不太关心大多数名称或位置,它关心主编号,以便它可以选择正确的驱动程序,而驱动程序(通常)关心次编号,以便它可以选择正确的实例。

大多数名称只是约定俗成的(尽管有些是由 POSIX 定义的)。另请注意,一个设备可能会注册多个主设备号,请sd在 中检查驱动程序/proc/devices;驱动模块名称(.ko)不必与设备名称相同,也不必与 中的设备节点相同/dev,并且单个驱动模块可以管理多个逻辑/物理设备或设备名称。


回顾一下:您可能有两个或多个设备节点(在其中/dev/或其他地方),它们具有相同的主要:次要编号,但如果它们是相同的类型,则它们引用相同的设备。您可以拥有一个可以处理多个主要实例的驱动程序,但在内核和驱动程序内,对于每种类型(字符或块),主要:次要数字用于引用特定设备(主要)和特定实例(次要)的设备。

您不能拥有两个具有相同类型和主要:次要的设备节点,并期望它们访问两个不同的逻辑或物理设备。当访问设备时,内核根据类型和主设备号(以及不是基于设备节点名称),并且按照惯例,次要编号确定性地选择特定实例或子功能。


更新 一些有趣的历史和一些 *BSD 观点可以在 Poul-Henning Kamp 的 2002 年中找到BSDCon推介会: https://www.usenix.org/legacy/events/bsdcon/full_papers/kamp/kamp_html/

如果你时光倒流至 1978 年(阿尔卡特朗讯提供)贝尔系统技术杂志1978 年 7 月至 8 月)Unix分时系统' 明确指出(p1937):

设备由主设备号、次设备号和类别(块或字符)来表征。对于每个类,都有一组设备驱动程序的入口点。主设备号用于在调用特定设备驱动程序的代码时对数组进行索引。次设备号作为参数传递给设备驱动程序。除了驱动程序赋予的意义外,次要编号没有其他意义。通常,驱动程序使用次设备号来访问多个相同物理设备之一。

答案2

当通过 创建设备文件时mknode,将提供major和编号。minor这些是 Linux 识别与设备文件关联的底层硬件设备的方式。在大多数情况下,它们major通过编号来标识驱动程序,同时minor区分驱动程序控制的不同设备。

因此,每个设备的编号必须是唯一的,否则不可能为所有设备创建正确的设备文件。

答案3

不,在 Linux 上它们并不总是唯一的。

Linux 使用devpts虚拟文件系统来提供伪终端 (ptys),并且该虚拟文件系统可以在不同位置多次挂载,这在设置 chroot 或命名空间容器时非常实用。虽然major:minor元组在文件系统实例上是唯一的devpts,但它在正在运行的系统上并不唯一:

# mount -t devpts devpts /dev/pts
# script -q /dev/null
# stat -c '%n %t:%T   %d:%i' `tty`
/dev/pts/0 88:0   34:3
# mount -t devpts devpts /dev/pts
# script -q /dev/null
# stat -c '%n %t:%T   %d:%i' `tty`
/dev/pts/0 88:0   35:3

在上面的示例中,该script(1)命令创建一个伪终端并在其中运行一个 shell。很明显,第一个script进程创建的伪终端与第二个进程创建的伪终端不同,但它们具有相同的名称和主要、次要编号。

为了唯一地标识伪终端,您需要使用它们的device:inode元组,或者将(devpts 文件系统的)设备号与其major:minor.问题是 tty 的“tty”字段/proc/PID/stat(第 7 个,请参阅联机帮助页;这是类似或从中获取信息的proc(5)工具的地方)仅包含tty 的(已打包的);如果这是一个 pty 从属设备,则不会向提供它的文件系统提供任何指示。同样的问题会影响通过 ioctl 获取的设备号。lsofpsst_rdevmajor:minordevptsTIOCGDEV

似乎没有任何可靠的方法来识别 Linux 上进程的控制终端。

相关内容