What are Linux Device Nodes With mknod-Free Embedded Linux Training

Linux Device Nodes With mknod

Learn how Linux exposes hardware as files, and how to create device nodes by hand in this free embedded Linux course

If you have ever wondered why a serial port shows up as /dev/ttyS0 or why plugging in a USB drive makes a new file appear under /dev, this lecture is for you. This is part of EmbeddedPathashala’s free embedded Linux course, and today we dig into linux device nodes — the mechanism that lets user-space programs talk to kernel drivers through nothing more than open(), read(), and write(). Whether you are building a minimal root filesystem for a custom board or just trying to understand how Linux really works under the hood, understanding linux device nodes is a foundational skill for anyone taking a free linux device drivers course seriously.

device nodes
mknod
major minor numbers
character devices
block devices
devtmpfs
udev
free embedded linux course

What You Will Learn

  • Why “everything is a file” in Linux
  • Character vs block devices
  • Major and minor numbers explained
  • Creating nodes manually with mknod
  • Setting correct permissions with -m
  • Why modern systems auto-create nodes
  • Common mistakes and how to debug them

Prerequisites

Before this lecture, you should be comfortable with basic Linux shell commands (cd, ls, sudo) and have a rough idea of what a root filesystem is. If you haven’t yet, it helps to have gone through the earlier lectures in this free embedded systems course on staging a root filesystem and setting up POSIX permissions, since device nodes live inside that same staging tree under /dev.

Everything Is (Almost) a File

One of the defining ideas behind Unix, and by extension Linux, is that hardware devices should be accessible through the same file-based interface as regular files: open(), read(), write(), and close(). Instead of every application needing a custom API for every peripheral, a serial port, a temperature sensor, or a disk controller can all be manipulated using ordinary file operations. The one well-known exception is networking — network interfaces are accessed through sockets, not device nodes, because the socket API is a better fit for packet-oriented, connection-based communication.

A device node (sometimes called a “special file”) is the entry in the filesystem that represents one of these devices. It doesn’t hold data the way a regular file does; instead, when a program opens it, the kernel routes that open call to the driver responsible for the underlying hardware. The conventional location for these nodes is the /dev directory, though on a minimal staged root filesystem you may be creating /dev from scratch yourself.

How a Read Reaches the Driver
Application
|
| read(fd, buf, len)
v
VFS (Virtual Filesystem Switch)
|
| looks up device node type + major/minor
v
Character or Block Device Driver
|
| driver-specific read handler runs
v
Physical Hardware (UART, sensor, storage controller…)

Character Devices vs Block Devices

Every non-network device node falls into one of two categories:

Type Symbol Access Pattern Typical Examples
Character device c Byte stream, usually sequential, often unbuffered by the block layer UART/serial ports, GPIO chardevs, sensors, /dev/null, /dev/console
Block device b Fixed-size blocks, randomly addressable, cached by the block layer SD cards, eMMC, NVMe/SATA drives, loop devices

A character device is, loosely, “anything that isn’t a block device and isn’t a network interface.” Block devices are specifically mass-storage devices, because only mass storage benefits from the page cache, I/O scheduling, and partition tables that the block layer provides.

Major and Minor Numbers

Every device node carries two numbers that the kernel uses to route requests to the correct driver:

  • Major number — identifies which driver handles the device. Historically it mapped to a specific driver, though modern Linux increasingly uses dynamically allocated majors for many driver classes.
  • Minor number — identifies which specific instance of that driver’s device you mean, since one driver can back multiple physical devices (e.g. ttyS0, ttyS1, ttyS2).

The kernel documents standard allocations for well-known devices in its source tree, in Documentation/admin-guide/devices.txt (this has moved location across kernel versions, so it’s always worth checking your specific kernel’s documentation directory rather than trusting an old book). You can also inspect currently registered major numbers live on a running system:

$ cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
 10 misc
...
Block devices:
259 blkext
  8 sd
 11 sr
259 nvme

Creating Device Nodes With mknod

The mknod command (“make node”) creates a device node manually. Its syntax is:

mknod <name> <type> <major> <minor>

Where type is c for a character device or b for a block device. Creating a node requires root privileges, since it grants direct access to kernel-managed hardware routing. Let’s walk through a realistic example: building the two device nodes every minimal root filesystem needs to boot with a shell — console and null.

$ mkdir -p ~/ep_rootfs/dev
$ cd ~/ep_rootfs
$ sudo mknod -m 666 dev/null c 1 3
$ sudo mknod -m 600 dev/console c 5 1
$ ls -l dev
total 0
crw------- 1 root root 5, 1 Aug 13 10:02 console
crw-rw-rw- 1 root root 1, 3 Aug 13 10:02 null

Notice the -m flag: it sets the file mode (permissions) at creation time, the same way chmod would afterwards. /dev/console is restricted to 600 (owner read/write only) because it’s the system console and should only be touched by root. /dev/null is 666 (read/write for everyone) because any process on the system should be able to discard output or read an empty stream from it.

To remove a device node, there is no special “unmknod” command — since a node is just a special kind of directory entry, the ordinary rm command works fine:

$ sudo rm dev/console

Why You Rarely Run mknod by Hand Today

On a full desktop or server Linux distribution, you will almost never run mknod yourself. Two mechanisms handle this automatically:

  • devtmpfs — a kernel-managed virtual filesystem, mounted at /dev, that automatically creates a node the moment a driver registers a device, and removes it when the device goes away. Most modern kernels mount this by default very early in boot.
  • udev (or its lighter cousin mdev in BusyBox-based systems) — a user-space daemon that listens for kernel uevents and can apply naming rules, symlinks, and permission policies on top of what devtmpfs creates.

Manual mknod still matters in two situations you’ll actually run into as an embedded developer: bootstrapping a minimal root filesystem before any device manager is running (you need at least console and null to get a shell up), and creating nodes inside containers or chroots that don’t have their own kernel driver events to react to.

Common Mistakes and Troubleshooting

Wrong major/minor numbers

If you type the wrong major/minor pair, the node will exist but will either fail to open or connect to the wrong driver entirely. Always cross-check against /proc/devices on the target kernel rather than trusting numbers from an old reference.

Forgetting root privileges

mknod without sudo (or without CAP_MKNOD) fails with “Operation not permitted.” This is intentional — device nodes are a privileged gateway to hardware.

Overly permissive modes

Setting a sensitive device node to 666 “just to make it work” is a common shortcut that becomes a security hole. Always match the mode to who legitimately needs access.

Creating nodes on a filesystem that doesn’t preserve special files

Some filesystems or archive/copy tools don’t preserve device node type and major/minor metadata. If your nodes turn into empty regular files after copying your staging tree, use tools that explicitly support special files (such as cp -a or tar with proper flags) rather than a naive recursive copy.

Best Practices

  • Prefer letting devtmpfs/udev manage /dev on any system where a kernel is fully booted — reserve manual mknod for the minimal early-boot nodes.
  • Keep permissions as tight as the use case allows; don’t default to 666.
  • Document any manually created nodes in your build scripts so the root filesystem is reproducible, rather than hand-crafting /dev interactively and forgetting what you did.

Security Considerations

Device nodes are a direct line into kernel-managed hardware, so their permissions are a real attack surface. A world-writable node for a storage device or a raw memory device (/dev/mem-style nodes) can let an unprivileged process read or corrupt data far outside its normal reach. When you are building a custom root filesystem, audit every node’s mode explicitly rather than copying a permissions scheme from an unrelated project.

Summary and Key Takeaways

  • Device nodes let user space talk to drivers using ordinary file operations — network interfaces are the one exception, handled via sockets instead.
  • Nodes are either character (c) or block (b) devices, distinguished by their access pattern.
  • Major numbers select the driver; minor numbers select the specific device instance.
  • mknod <name> <type> <major> <minor> creates a node manually; rm deletes one.
  • A minimal bootable root filesystem needs at least console and null.
  • devtmpfs and udev/mdev automate node creation on a running system — manual mknod is mainly for early boot and minimal environments.

Conclusion

Device nodes are one of those pieces of Linux plumbing that quietly make the “everything is a file” philosophy actually work. For most day-to-day development you’ll rely on devtmpfs and udev to manage /dev automatically, but understanding how to create nodes by hand with mknod — and exactly what major and minor numbers mean — is essential once you’re staging a minimal root filesystem from scratch, which is exactly the kind of hands-on skill this free linux device drivers course is built around. In the next lecture, we’ll look at the proc and sysfs pseudo filesystems, which give you an entirely different, dynamic window into kernel state.

Frequently Asked Questions

What is the difference between a device node and a regular file?

A regular file stores data on a filesystem; a device node stores no data itself but instead tells the kernel which driver (major number) and which device instance (minor number) to route file operations to.

Do I always need to run mknod manually on Linux?

No. On systems with devtmpfs and udev running, nodes are created and removed automatically as drivers register devices. Manual mknod is mostly needed for minimal early-boot root filesystems.

Why does /dev/null need mode 666?

Because any process on the system, regardless of privilege level, needs to be able to discard writes or read an empty byte stream from it — restricting it would break countless programs that rely on it.

How do I find the major and minor numbers for a device on my kernel?

Check /proc/devices on a running system with the driver loaded, or consult your kernel version’s device numbering documentation rather than an old book, since allocations can change between kernel releases.

Can I create a device node inside a Docker container?

Only with the appropriate capability (CAP_MKNOD) and, in most container runtimes, only if the container has been granted device access — by default containers are restricted from creating arbitrary device nodes for security reasons.

What happens if I get the major/minor numbers wrong?

The node will still exist as a file, but opening it will either fail or silently attach to the wrong driver, since the kernel routes purely based on those two numbers, not the node’s name.

Is a character device always slower than a block device?

Not necessarily — the distinction is about access pattern (byte-stream vs block-addressable with caching), not raw speed. Many character devices, like high-throughput sensor interfaces, are perfectly fast.

Keep Learning Embedded Linux for Free

This lecture is part of EmbeddedPathashala’s free embedded Linux course covering the kernel, drivers, and root filesystem construction from the ground up.

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *