Linux device-number allocation 2026-11-05
Linux device-number allocation assigns or reserves the numerical identifiers through which device-special interfaces are registered. The relevant identity includes device type together with major device number and minor device number. It is distinct from naming a device node, assigning its inode number, or obtaining a process-local file descriptor.
The kernel's allocated-device list records established assignments. For example, character major 1 includes minor 3 for
/dev/null and minor 5 for /dev/zero. The same integer major 1 has a separate block-device allocation for RAM disks. These entries concern different interface namespaces, not interchangeable interpretations of a single untyped integer.[ref]Linux allocated devices in the Linux kernel documentation. Entry 1, character memory devices and block RAM disks
For character devices, the kernel API separates requesting a particular range with
register_chrdev_region from dynamic character-device number allocation with alloc_chrdev_region. The latter receives a first minor and count, chooses the major dynamically, and returns the first assigned combined device number. The caller must check whether reservation succeeded.[ref]Character-device number registration in the Linux kernel documentation. Char devices, register_chrdev_region and alloc_chrdev_region
An original allocation example requests four minor values starting at 20. If the returned major is , the reserved range in this example isIt does not contain . Code should use the returned rather than guess a major from an earlier machine or boot. A numerical allocation can serve software interfaces as well as physical hardware, so four minors do not necessarily imply four physical peripherals.
Reserving numbers is only one step. The character-device object must also be associated with its operations and added to the kernel;
cdev_add makes it live. Separately, userspace needs an appropriate device node or other naming arrangement. The registration name used for bookkeeping is not itself a pathname under /dev.[ref]Character-device number registration in the Linux kernel documentation. Char devices, cdev_init, cdev_add and __register_chrdev name description
This separation explains a common diagnostic trap. Creating a node containing a chosen major/minor pair does not reserve that range or supply a working device driver. Conversely, allocating a range does not make every invented pathname reach it. Inspect the actual registered interface, file type and stored device number together when identifying a device.
The allocation is also not a persistent hardware serial number. Dynamic assignment can differ between configurations or registration histories. Releasing a number range with
unregister_chrdev_region returns the reservation; a complete driver teardown must also handle the device object's lifetime and existing users. The kernel documentation notes that deleting a character-device object prevents new opens while operations on already open descriptors can remain possible.[ref]Character-device number registration in the Linux kernel documentation. Char devices, unregister_chrdev_region and cdev_del lifetime note
Unwinding a failed character-device registration releases resources acquired before an initialization failure while preserving the lifetime of anything that concurrent users can still access. In Linux, reserving device numbers, publishing the character-device object and creating userspace-visible names are distinct steps. The cleanup path must know which steps actually succeeded.
Consider an original abstract initialization sequence: reserve a number range, initialize a character-device object, publish it, then finish a later setup step. The following table tracks successful acquisitions; it is not a complete driver implementation.
| State reached | Range reserved? | Character device live? | Required response to a later failure |
|---|---|---|---|
| Before reservation succeeds | No | No | Do not release a range that was not acquired. |
| Reservation succeeded, publication not reached | Yes | No | Release that reserved range and other private resources already acquired. |
| Publication succeeded | Yes | Yes | Stop new access, unwind the reservation, and preserve storage needed by existing users. |
alloc_chrdev_region reserves a range and reports failure through its return value. cdev_init initializes the object with its operations; cdev_add publishes it and makes it live immediately. unregister_chrdev_region releases a successful number reservation. Pair each release with the acquisition that actually succeeded, using the same first number and count.[ref]Character-device number registration in the Linux kernel documentation. Char devices, alloc_chrdev_region, cdev_init, cdev_add and unregister_chrdev_region
For a concrete bookkeeping example, suppose a successful reservation contains four interfaces starting at returned pair . Failure before publication requires releasing that four-number range. Releasing only three leaves part of the reservation behind; releasing a guessed starting major or an unacquired range is a different error. The returned major from dynamic character-device number allocation must be retained rather than reconstructed from a pathname.
Publication changes the lifetime problem.
cdev_del prevents new opens, but existing open file descriptors can still invoke their file operations. Therefore removing the device from lookup is not a proof that its backing state can immediately be freed. Character-device lifetime after deletion must account for the references and callbacks already in progress.[ref]Character-device number registration in the Linux kernel documentation. Char devices, cdev_del lifetime note
The combined
cdev_device_add helper has an especially important failure contract: callers must assume userspace could open the device and call operations even if the helper returns failure. A blanket error handler that immediately frees all backing state would violate that contract.[ref]Character-device number registration in the Linux kernel documentation. Char devices, cdev_device_add note
Design ownership and reference handling around the documented publication boundary, then release each owned resource once. The general lesson is that reverse acquisition order must be combined with concurrency-aware lifetime management.