open atlas
↑ Back to track
Linux, the operating system LIN · 01 · 04

procfs and sysfs

/proc and /sys are virtual filesystems the kernel generates on demand in RAM — no bytes on disk. They expose live process tables, memory maps, CPU info, and hardware tunables as ordinary files you can cat, grep, and in /sys even write to change kernel behavior at runtime.

LIN Junior ◷ 22 min
Level
FoundationsJuniorMiddleSenior

You want to know how much memory is free right now. You run free -h. Somewhere that number comes from — and it is not a database query or a daemon that polls hardware. The kernel exposes live memory accounting as a text file at /proc/meminfo. The moment you cat it, the kernel assembles the content from internal data structures and hands it to you. When you close the file, the content disappears. There is nothing on disk.

This is the design: the kernel exports its own state as a filesystem. /proc and /sys are the two main windows. Understanding what lives there is the difference between guessing at system state and reading it directly from the source.

Goal

After this lesson you can use /proc/meminfo, /proc/cpuinfo, and /proc/<PID>/ entries to inspect live system state, use /sys to read hardware and driver information, and explain why these files are generated on demand rather than persisted to disk.

1

procfs (/proc) is a virtual filesystem mounted at boot. The kernel registers a special filesystem type called proc. When the system boots, systemd mounts it at /proc. No disk space is allocated — there are no blocks, no inodes in the traditional sense. Every time you open a file under /proc, the VFS (Virtual Filesystem Switch) calls a kernel function that builds the response in memory and returns it. When you close the file descriptor, the memory is freed.

mount | grep proc
# proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
ls /proc
# you see numbered directories (PIDs) plus global files like meminfo, cpuinfo

The numbered directories are processes. /proc/1/ is PID 1 (systemd). /proc/$$ is your current shell (bash expands $$ to its PID).

2

Global /proc files expose system-wide kernel state. These are the files you read most often in diagnostics:

cat /proc/meminfo          # all memory counters in kB: MemTotal, MemFree, Cached, Buffers…
cat /proc/cpuinfo          # per-core: model name, MHz, cache size, CPU flags
cat /proc/loadavg          # 1/5/15-min load averages + running/total task counts
cat /proc/uptime           # seconds since boot (two numbers: total, idle time)
cat /proc/version          # kernel version string
cat /proc/mounts           # currently mounted filesystems (same as /etc/mtab on modern systems)
cat /proc/net/tcp          # TCP socket table in hex (ss and netstat read this)

Tools like top, htop, free, uptime, and netstat get their data by reading these files and reformatting the output. Understanding the source makes you independent of these tools — on a minimal container with no top installed, you can still diagnose memory pressure by reading /proc/meminfo directly.

3

Per-process directories give you a live view of any process. For any PID you can read:

PID=1
ls /proc/$PID/

cat /proc/$PID/status      # state (running/sleeping), Uid, Gid, memory usage (VmRSS, VmSize)
cat /proc/$PID/cmdline     # the full command line (null-separated, use tr '\0' ' ')
cat /proc/$PID/environ     # environment variables (null-separated)
ls -la /proc/$PID/fd/      # open file descriptors (each is a symlink to the real file/socket)
cat /proc/$PID/maps        # virtual memory map: every segment with permissions and backing file
cat /proc/$PID/net/tcp     # network connections for this PID's network namespace

The fd/ subdirectory is especially useful: it shows exactly which files a process has open. If a process is holding a deleted file open (common cause of “disk full but no large files found”), you can see it here:

ls -la /proc/$PID/fd/ | grep deleted
4

sysfs (/sys) exposes kernel objects and hardware tunables. While /proc was originally for process info (and accumulated many globals over time), /sys was designed from the start as a structured representation of the kernel’s internal object hierarchy — devices, buses, drivers, power management.

ls /sys/block/             # block devices (disks)
cat /sys/block/sda/size    # disk size in 512-byte sectors
cat /sys/class/net/        # network interfaces
cat /sys/class/net/eth0/speed        # link speed in Mbps
cat /sys/class/net/eth0/carrier      # 1 = link up, 0 = down
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq   # current CPU frequency in kHz

Unlike /proc which is mostly read-only globals, many /sys entries are writable — writing to them changes kernel behavior immediately:

# Example: disable CPU frequency scaling (for latency-sensitive workloads)
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

These changes are not persistent across reboots. Persistent kernel parameter changes go through sysctl (covered in unit 12).

5

The performance implication: reading /proc is nearly free. A cat /proc/meminfo involves no disk I/O, no daemon roundtrip, no network call. The kernel assembles the response in microseconds. This is why shell scripts for monitoring often grep /proc directly — it is faster and more reliable than parsing tool output.

The caveat: some /proc reads acquire kernel locks briefly. On a system under extreme load, cat /proc/PID/maps for a process with thousands of memory mappings can block for milliseconds. And reading /proc/net/tcp on a server with hundreds of thousands of connections involves a full kernel-side table scan. Know what you are reading before you script it in a tight loop.

Worked example

Find which process is holding a port open, without netstat or lsof.

# /proc/net/tcp lists all TCP connections in hex
# Column 2 is local address (hex IP:port), column 4 is state (0A = LISTEN)
grep ' 0A ' /proc/net/tcp

# The inode column (column 10) links back to a process
# Find which process owns that inode:
inode=12345   # replace with the inode number from the grep above
ls -la /proc/*/fd 2>/dev/null | grep "socket:\[$inode\]"
# The PID is in the path: /proc/<PID>/fd/<n> -> socket:[12345]

This is exactly what ss -tlnp and lsof -i :PORT do internally — they parse /proc/net/tcp and match inodes to process file descriptors via /proc/<PID>/fd/. The tools are conveniences; the data lives in /proc.

Why this works

macOS has no /proc or /sys. The equivalent is sysctl -a (which reads from the kernel’s sysctl MIB) and dtrace/fs_usage for process-level introspection. The “everything is a file” model is a Linux/Unix philosophy, but macOS chose different mechanisms. When Docker runs a Linux container on your Mac, the container sees a real /proc — it is the Linux kernel inside HyperKit that provides it, not macOS.

Common mistake

A classic trap: you delete a large log file to free up disk space, but df still shows the filesystem as full. The reason is that a running process (say, nginx) still has the file open via a file descriptor. On Linux, a file’s disk blocks are not freed until all file descriptors pointing to it are closed, even if the directory entry (the name) was removed. Find the culprit with ls -la /proc/*/fd 2>/dev/null | grep deleted — then either restart the process or send it SIGHUP to reopen its log files.

Check yourself
Quiz

You run: cat /proc/meminfo. At what point is the output actually written to the /proc/meminfo file on disk?

Recap

procfs (/proc) and sysfs (/sys) are virtual filesystems the kernel generates entirely in RAM — there is nothing on disk. Reading /proc/meminfo, /proc/cpuinfo, or /proc/<PID>/status invokes a kernel handler that assembles the output from live internal data structures. /proc/<PID>/fd/ shows every open file descriptor for a process; /proc/net/tcp contains the raw TCP connection table. /sys exposes the kernel’s hardware object hierarchy and provides writable tunables you can change at runtime. Tools like free, ps, ss, and netstat all read from these virtual files and reformat the output — you can always go to the source directly.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 4 done

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources1
expand
  1. 01

Trademarks belong to their respective owners. Editorial reference only.