Skip to content

VFS — tmpfs devtmpfs cgroupfs


Linux exposes much more than ordinary disk-backed filesystems. You’ve already seen /proc and /sys, where the kernel exposes information through filesystem-like trees. There are a few other virtual filesystems worth recognizing because you’ll encounter them regularly on a running Linux system.

This chapter focuses on three of them: tmpfs, devtmpfs, and cgroupfs. You don’t need to manage all three directly at this point; the goal is to understand what they are, why they exist, and how to recognize them when inspecting a system.

tmpfs: A Filesystem Backed By Memory

tmpfs is a filesystem whose contents are kept in memory rather than permanently stored on a disk.

You can see it on a normal Debian system with:

df -h -t tmpfs

Typical output may look like:

Filesystem      Size  Used Avail Use% Mounted on
tmpfs           794M  2.0M  792M   1% /run
tmpfs           3.9G     0  3.9G   0% /dev/shm

The exact sizes depend on the machine, but the important part is the filesystem type: tmpfs and the mount points.

Unlike an ordinary filesystem such as ext4, tmpfs does not represent persistent disk storage. Its contents disappear when the system is rebooted.

That makes it useful for data that needs normal filesystem semantics but does not need to survive a reboot.

Why Does tmpfs Exist?

Programs often need temporary files, sockets, runtime state, or shared-memory objects. Putting all of that on a physical disk would be unnecessary in many cases.

With tmpfs:

Application
  tmpfs file
   memory

The application still sees ordinary files and directories. The underlying storage behavior is different.

This is one of the useful ideas behind virtual filesystems: the filesystem interface can stay the same even though the underlying storage is not a traditional disk filesystem.

tmpfs Is Not Simply “RAM Disk”

Calling tmpfs a RAM disk is convenient, but slightly misleading. tmpfs uses memory resources and can also make use of swap. It is dynamically sized rather than being a fixed block of RAM reserved permanently when mounted.

For example, if a tmpfs mount has a maximum size of 1G, that does not mean 1 GiB of physical RAM is immediately consumed. Memory is used as files are actually created and populated.

/run: Runtime System State

One of the most important tmpfs mounts is:

/run

Inspect it:

findmnt /run

You may see:

TARGET SOURCE FSTYPE OPTIONS
/run   tmpfs  tmpfs  rw,nosuid,nodev,noexec,...

/run contains runtime state created since the system booted: PID files, sockets, service state, and other information that does not need to survive a reboot.

For example, system services may place Unix sockets under /run/.

Because /run is temporary runtime state, losing its contents during reboot is expected. The directory itself is recreated during the next boot.

/dev/shm: Shared Memory

Another common tmpfs mount is:

/dev/shm

Check it:

findmnt /dev/shm

It is commonly used for POSIX shared-memory objects.

You can think of it as a memory-backed filesystem exposed through an ordinary directory:

/dev/shm
   tmpfs
   memory

Applications that need to exchange data through shared memory can use this interface without treating the data as persistent disk storage.

Creating A tmpfs Mount

You can create your own temporary filesystem to see the idea directly.

First create a mount point:

sudo mkdir /mnt/temporary

Then mount a 100 MiB tmpfs:

sudo mount -t tmpfs -o size=100M tmpfs /mnt/temporary

Check it:

df -h /mnt/temporary

You should see something similar to:

Filesystem      Size  Used Avail Use% Mounted on
tmpfs           100M     0  100M   0% /mnt/temporary

Now create a file:

sudo sh -c 'echo "temporary data" > /mnt/temporary/example.txt'

The file behaves like a normal file:

cat /mnt/temporary/example.txt

But the storage is provided by tmpfs, not by an ext4 filesystem on a disk.

Unmount it:

sudo umount /mnt/temporary

The file disappears because the filesystem that contained it no longer exists.

You can then remove the empty mount point:

sudo rmdir /mnt/temporary

Note

This example is intentionally temporary. If you add a tmpfs entry to /etc/fstab, it can be mounted automatically at boot, but that is unnecessary for understanding the concept here.

devtmpfs: Where /dev Comes From

You’ve already used paths such as:

/dev/sda
/dev/null
/dev/tty

It is easy to think of /dev as simply a directory containing special files that were created permanently on disk. Modern Linux systems are more dynamic than that.

The /dev hierarchy is normally backed by devtmpfs, a kernel-managed virtual filesystem containing device nodes.

Check it:

findmnt /dev

On a typical system you may see:

TARGET SOURCE   FSTYPE   OPTIONS
/dev   devtmpfs devtmpfs rw,nosuid,...

The important part is:

FSTYPE
    devtmpfs

The kernel creates device nodes in this filesystem as devices become known to it.

So the relationship is roughly:

Hardware / kernel device
       devtmpfs
         /dev
          ├── /dev/sda
          ├── /dev/tty
          └── /dev/null

The exact devices present depend on the machine.

Why Does Linux Need /dev?

Programs need a filesystem-visible way to interact with devices.

For example:

/dev/sda

represents a block device.

/dev/tty

represents a terminal device.

/dev/null

is a special character device that discards data written to it.

These are not ordinary files containing the device’s data. They are device nodes that provide an interface through which programs can interact with kernel-managed devices.

That is why commands can use paths such as:

cat /dev/null

or:

sudo fdisk /dev/sda

The path looks like a normal filesystem path, but the object ultimately represents a kernel device.

devtmpfs And udev

There are two related pieces here that are easy to confuse.

devtmpfs provides the basic device nodes managed by the kernel. udev operates in userspace and manages device events and additional device-node handling, including permissions and useful names or symlinks.

Conceptually:

Kernel detects device
    devtmpfs
     /dev node
      udev
   userspace management

You don’t need to turn this into a full udev lesson here. The useful distinction is simply:

devtmpfs is the kernel-side virtual filesystem behind the basic /dev device nodes; udev is the userspace device-management system that works around those nodes.

cgroupfs: A Filesystem Interface To Control Groups

The third filesystem is different in purpose.

Linux control groups, or cgroups, provide mechanisms for grouping processes and controlling or accounting for their resource usage.

You’ve already encountered cgroups conceptually in the Docker material, but here the important point is how Linux exposes them.

Cgroups are represented through a filesystem interface commonly mounted as:

/sys/fs/cgroup

Check it:

findmnt /sys/fs/cgroup

On a modern Debian system using cgroup v2, you may see:

TARGET         SOURCE FSTYPE  OPTIONS
/sys/fs/cgroup cgroup cgroup2 rw,nosuid,nodev,noexec,...

The filesystem type may therefore appear as cgroup2 rather than the older cgroup.

The important idea is that cgroups are represented as a filesystem tree that the kernel understands.

What Does A Cgroup Filesystem Look Like?

A simplified cgroup v2 tree might look like:

/sys/fs/cgroup/
├── cgroup.controllers
├── cgroup.procs
├── cpu.max
├── memory.current
├── memory.max
└── ...

These files are not ordinary configuration files stored on disk. They are kernel interfaces.

Reading one can expose current state:

cat /sys/fs/cgroup/memory.current

Writing an appropriate value can change the configuration of that cgroup.

For example, a cgroup may expose:

memory.max

which controls the memory limit for processes belonging to that cgroup.

The exact files and behavior depend on the cgroup version and configuration, which is why you should treat this tree as a kernel interface, not as an ordinary directory of files.

Why Use A Filesystem Interface For Cgroups?

The filesystem interface gives administrators and programs a familiar way to interact with kernel functionality.

Instead of inventing an entirely separate mechanism for every operation, Linux can expose state and controls through files:

read file
ask kernel for state

write file
request a kernel change

This is the same broad idea you’ve already seen with /proc/sys and sysctl.

The important difference is what the filesystem represents:

/proc
    → process and kernel information

/sys
    → devices, drivers, and kernel objects

/sys/fs/cgroup
    → process groups and resource controls

The Three Filesystems Side By Side

FilesystemCommon LocationMain PurposePersistence
tmpfs/run, /dev/shmMemory-backed temporary filesLost on reboot
devtmpfs/devKernel-managed device nodesRecreated dynamically
cgroup2/sys/fs/cgroupProcess grouping and resource controlKernel-managed state

The key difference is that these filesystems exist for very different reasons.

tmpfs
    → temporary storage

devtmpfs
    → device interface

cgroupfs / cgroup2
    → process/resource control

They all look like filesystems because Linux gives them a filesystem interface, but none should be confused with an ordinary disk filesystem such as ext4.

How To Recognize Them On A Real System

When investigating an unfamiliar machine, findmnt is a useful way to see what filesystem is behind a path:

findmnt /run
findmnt /dev
findmnt /sys/fs/cgroup

You can also inspect the filesystem type with:

df -T /run /dev /sys/fs/cgroup

The exact output varies by distribution and system configuration, but you should recognize entries such as:

tmpfs
devtmpfs
cgroup2

This is useful because a path ending in a familiar directory name doesn’t tell you what is actually providing it.

For example:

/run
tmpfs

/dev
devtmpfs

/sys/fs/cgroup
cgroup2

The mount table is what tells you the underlying filesystem type.

One Mental Model For Virtual Filesystems

At this point, the different virtual filesystems can be viewed as different interfaces exposed through the same general filesystem model:

                    Linux VFS
        ┌──────────────┼──────────────┐
        │              │              │
      procfs         sysfs          tmpfs
        │              │              │
   processes &      devices &      temporary
   kernel state      drivers        storage
        └──────────────┐
                  /proc/sys
                   sysctl

                    /dev
                  devtmpfs
                 device nodes

                /sys/fs/cgroup
                    cgroup2
              process/resource control

The important concept isn’t memorizing every filesystem type. It is recognizing that Linux can expose kernel state, hardware, runtime storage, and resource-control mechanisms through filesystem interfaces that ordinary tools can inspect.

What You Should Remember

tmpfs gives you temporary filesystem storage backed primarily by memory. /run and /dev/shm are common examples, and their contents are not intended to survive a reboot.

devtmpfs provides the basic device nodes under /dev, giving programs filesystem paths through which they can interact with kernel-managed devices.

cgroup2 provides a filesystem interface for Linux control groups, exposing process grouping and resource-control state through paths such as /sys/fs/cgroup.

The common thread is:

They look like filesystems
but they do not represent ordinary persistent disk data

That distinction becomes very useful when you’re inspecting a Linux system and encounter a directory whose contents clearly don’t behave like normal files on disk.

Last updated on