Skip to content

How Linux Device Nodes Are Created

“Everything is a file” is a core Unix/Linux idea. Even non-file resources are commonly exposed through file-like interfaces for access, read/write control, and configuration. This article focuses on character-device drivers: how their device files are created and removed, the relevant kernel interfaces, and a practical serial-driver example.

1. Device files

A device file represents a hardware-related resource. It lets an application access a system resource without needing to know how the underlying hardware works. The driver itself is part of the Linux kernel.

  • From user space: a program can open, read, write, and sometimes memory-map it like an ordinary file.
  • From the kernel: the kernel identifies the request, forwards it to the matching driver, and the driver performs the required operation.

For example:

ls -al /dev

You will find many nodes, such as serial ports like /dev/ttymxc2 and video devices like /dev/video*.

A subset of device nodes

2. Creating a driver device file

Device nodes are normally created by the kernel driver, although they can also be created manually for testing.

2.1 Key objects

The central structures are struct class and struct device, declared in include/linux/device/class.h and include/linux/device.h. The first describes a device class; the second describes an individual device.

Device-node creation flow

Create the device class:

struct class *class_create(const char *name);

Create an individual device directory and its attributes:

struct device *device_create(struct class *class, struct device *parent,
                             dev_t devt, void *drvdata, const char *fmt, ...);
  • class: the class to which the device belongs.
  • parent: its parent device, or NULL.
  • devt: the device number, made from major and minor numbers.
  • drvdata: private driver data, or NULL.
  • fmt: the formatted device name.

2.2 Serial driver example

A UART is a TTY device, so it is closely tied to the TTY subsystem.

TTY device-node creation flow

The early steps register the UART information as a TTY device and add it through tty_cdev_add(). After the system enters the filesystem stage, char_dev_init() calls tty_init(), which eventually calls device_create() to create the visible device node.

2.3 Removal

Unregistering a driver device normally has two matching operations:

  1. Call device_destroy() to remove the device node from /dev and release its associated device object.
  2. Call class_destroy() to remove the class under /sys/class and release the class resources.

3.1 Major and minor numbers

A device file is identified by a major and a minor number.

  • A major number identifies a device type, such as character or block devices.
  • A minor number identifies one specific device within that type.

The kernel uses the MKDEV macro to construct a dev_t value.

Major/minor number example

3.2 File operations

A driver communicates with user space through file-operation callbacks, including:

  • open — open the device node
  • release — close it
  • read — read data from the device
  • write — write data to the device

4. Summary

The usual sequence is: create a device class, create the device and its attributes, then expose its node. The corresponding file operations are implemented by the driver and may also coordinate data exchange between kernel and user space.