Are the major, minor number unique

From The Linux Programming Interface, §14.1

Each device file has a major ID number and a minor ID number. The major ID identifies the general class of device, and is used by the kernel to look up the appropriate driver for this type of device. The minor ID uniquely identifies a particular device within a general class. The major and minor IDs of a device file are displayed by the ls ­-l command.

[...]

Each device driver registers its association with a specific major device ID, and this association provides the connection between the device special file and the device. The name of the device file has no relevance when the kernel looks for the device driver.

See also this old (2001) Linux Device Drivers (2e) chapter.

i.e. the intention is to provide a unique mapping of major:minor to device:instance for each type of device. Strictly, you can have two distinct devices with the same major: minor, as long as one is char and one is block:

# 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

On Linux, at any point in time on one system the major:minor numbers for each type of device are unique. The numbers may however change over time, and need not be the same on across different Linux systems (even the same distribution, kernel and hardware). Note that character and block devices have distinct numbering spaces, e.g. block major 1 is assigned to RAM disks, char major 1 is assigned to a set of kernel devices including null and zero.

Historically device majors were (mostly) statically allocated through a registry (also still present, though unmaintained, in the kernel source Documentation/devices.txt). These days many devices are allocated dynamically, this is managed by udev, and the mappings viewable in /proc/devices. The fixed devices still exists in incude/uapi/linux/major.h (recently moved from include/major.h)

Now although the major:minor combination uniquely identifies specific device instances, there's nothing to stop you creating multiple devices nodes (files) that refer to the same device. They don't even have to be created in /dev (but they do have to be on a filesystem that supports creating device nodes, and isn't mounted with the nodev option).

A common use is creating duplicate zero, null and random devices in a 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

The names are just aliases, the kernel doesn't care much about most names or locations, it cares about the major number so that it can select the correct driver, and the driver (usually) cares about the minor number so it can select the correct instance.

Most names are simply convention (though some are defined by POSIX). Note also that one device may register for multiple major numbers, check the sd driver in /proc/devices; a driver module name (.ko) need not be the same as the device name, and need not be the same as the device node in /dev, and a single driver module may manage multiple logical/physical devices or device names.


To recap: you may have two or more device nodes (in /dev/ or elsewhere) which have the same major:minor numbers, but if they are the same type they refer to the same device. You can have one driver which can handle multiple major instances, but within the kernel and within the driver, for each type (char or block) the major:minor number is taken to refer to a specific device (major) and a specific instance (minor) of the device.

You cannot have two device nodes with the same type and major:minor and expect them to access two different logical or physical devices. When a device is being accessed the kernel select one driver based on the type and the major number (and not based on the the device node name), and by convention the minor number deterministically selects a specific instance or sub-function.


Update Some interesting history and some *BSD perspective can be found in Poul-Henning Kamp's 2002 BSDCon presentation: https://www.usenix.org/legacy/events/bsdcon/full_papers/kamp/kamp_html/

If you leap back in time to 1978 (courtesy of Alcatel-Lucent, the Bell System Technical Journal Jul-Aug 1978) the 'Unix Time Sharing System' sets it out clearly (p1937):

Devices are characterized by a major device number, a minor device number, and a class (block or character). For each class, there is an array of entry points into the device drivers. The major device number is used to index the array when calling the code for a particular device driver. The minor device number is passed to the device driver as an argument. The minor number has no significance other than that attributed to it by the driver. Usually, the driver uses the minor number to access one of several identical physical devices.


When a device file is created by mknode, the major and minor numbers are supplied. These are how Linux identifies the underlying hardware device associated with a device file. In most cases they major number identifies the driver while the minor distinguishes the different devices the driver controls.

As such the numbers must be unique to each device or it would not be possible to create correct device files for all of them.