Understanding Device Management in Linux and Yocto: sysfs, /dev, devtmpfs, udev, and Device Tables
Introduction
In Linux systems, the kernel acts as the intermediary between user applications and hardware devices. Applications cannot directly interact with hardware; instead, they rely on the kernel to provide safe and standardized interfaces.
To expose hardware to user space, the Linux kernel relies on several mechanisms that provide abstractions over devices.
sysfs
A representation of Kernel Objects
sysfs is a pseudo-filesystem that exposes the Linux device model to user space.
It provides a structured representation of kernel objects such as devices, drivers, buses and subsystems. It is typically mounted at /sys.
Inside this filesystem, several directories represent different parts of the kernel device hierarchy:
/sys/class
/sys/devices
/sys/bus
Through sysfs, user space applications and users can view the state of devices managed by the kernel and configure some of their attributes. This virtual filesystem organizes devices into structured directories such as /sys/class/leds/, /sys/class/net/, and /sys/class/pwm/. Inside these directories, attribute files can be read to obtain information or sometimes written to modify device settings.
Device Nodes and the /dev Directory
Device nodes are special files that represent hardware devices and allow user space applications to communicate with them using standard system calls such as open(), read(), write(), and ioctl().
Each device node is associated with a kernel driver that controls the corresponding hardware.
Unlike regular files, device nodes serve as interfaces between user space and kernel drivers, enabling applications to access hardware in a uniform and controlled way.
Types of Devices in Linux
Devices are generally categorized into three types.
Character Devices:
Character devices are accessed as a stream of bytes, where data is read or written sequentially. They are controlled by character device node files under /dev.
Examples:
serial ports : /dev/ttyS0
GPIO interfaces : /dev/gpiochip0
Block Devices
Block devices operate on blocks of data, allowing buffered and random access operations. They are controlled by block device node files under /dev.
Examples:
SSDs: /dev/sda
SD cards: /dev/mmcblk0
Network Devices
Network interfaces are treated differently.
They do not appear as device nodes under /dev. Instead, they are managed by the networking subsystem and exposed through sysfs: /sys/class/net.
Major and Minor Numbers
Every device node in /dev is associated with two numbers: major number and minor number
These numbers allow the kernel to determine which driver should handle a given device file.
Major Number
The major number identifies the kernel driver responsible for managing the device.
All devices handled by the same driver typically share the same major number.
This number can either be:
- statically defined in the driver
- dynamically allocated by the kernel when the driver registers itself.
Minor Number
The minor number is used to differentiate individual devices that are handled by the same driver. The kernel itself does not interpret this number, it simply passes it along to help route the request to the correct driver. It is then up to the driver to interpret the minor number and use it to identify the specific device instance it needs to manage.
Example:
Consider two disk partitions:/dev/sda1 → major 8, minor 1
/dev/sda2 → major 8, minor 2
Both share the same major number (8) because they are handled by the same disk driver, while the minor number differentiates the partitions.
Creating Device Nodes
Device nodes can be created using several approaches depending on the system configuration.
Manual Creation with mknod
Device nodes can be created manually using the mknod utility.
The command syntax is:
mknod /dev/<device_name> <type> <major> <minor>
Note:
c → character device
b → block device
Get Oussema MAINSI’s stories in your inbox
Join Medium for free to get updates from this writer.
However, this approach requires root privileges and is not practical for managing many device.
devtmpfs: Kernel-Side Device Node Creation
Modern Linux systems use devtmpfs, a special filesystem managed directly by the kernel.
This filesystem is enabled through the following kernel configuration options:
CONFIG_DEVTMPFS enables support for the devtmpfs filesystem.
CONFIG_DEVTMPFS_MOUNT allows the kernel to automatically mount devtmpfs on /dev during system boot.
When a driver registers a device with the kernel, devtmpfs automatically creates a basic device node under /dev.
Automatic device node creation and management rely on a user space device manager.
Automatic Device Management with udev
Linux systems use udev, one of the most well-known device managers, to dynamically manage device nodes.
During system startup, a daemon called systemd-udevd is launched. This daemon runs in user space and listens for hardware events generated by the kernel.
The role of this daemon is to dynamically manage devices in user space. It is responsible for creating device nodes, assigning appropriate permissions, renaming devices, creating symbolic links, and triggering additional actions when hardware events occur.
The behavior of udev is defined through udev rule files, which are typically located in /etc/udev/rules.d and /lib/udev/rules.d.
These configuration files use the .rules extension.
Kernel Events and Device Creation
The interaction between the kernel and udev is based on events.
When a device appears in the system, the following sequence occurs:
- The kernel detects a hardware device.
- The kernel emits an uevent.
- The systemd-udevd daemon receives this event.
- The daemon evaluates the relevant udev rules.
- A properly configured device node is created under /dev.
This mechanism enables Linux systems to automatically handle dynamic hardware, known as hotplug devices, like USB peripherals.
Creating Device Nodes at Build Time with Device Tables
Another approach to creating device nodes is by using a device table.
A device table is a special configuration file used during the root filesystem build process.
It allows the creation of static device node entries without requiring root privileges on the host.
Using mknod manually requires elevated privileges, typically through sudo.
In contrast, device tables allow device nodes to be defined during the build process itself.
A device table entry typically specifies:
- device node path
- device type (c for character or b for block)
- permissions
- major number
- minor number
During the root filesystem generation, the build system parses this file and automatically inserts the corresponding device nodes into the generated filesystem image.
During the boot, when the kernel mounts this root filesystem, the device nodes already exist under /dev.
Yocto: Device Node Handling
In Yocto, automatic creation of device nodes using devtmpfs is controlled by the USE_DEVFS variable.
Setting USE_DEVFS to "1" enables devtmpfs support.
The filesystem created will be populated with devices listed in the device table specified by the IMAGE_DEVICE_TABLE variable. By default this variable points to device_table-minimal.txt in the meta layer of OpenEmbedded.
The choice of device manager is handled through the concept of a virtual package, allowing support for multiple managers. This is configured via the VIRTUAL-RUNTIME_dev_manager variable, which can be set to "udev", "busybox-devm", or "systemd".
For systems that require a persistent /dev and do not rely on dynamic device management, USE_DEVFS should be set to "0".
In this case, the device nodes are created from the specified device table file defined by IMAGE_DEVICE_TABLE, allowing a static /dev hierarchy at build time.







