/proc: the kernel as a filesystem
Every process tool in this module reads /proc: explore a process's directory, the system-wide files and the tunables in /proc/sys, then prove the whole module in an exam.
What you will learn
- Explain what `/proc` is and why its files show size 0 but have content.
- Read a process's status, command line, working directory, open files and environment from `/proc/PID`.
- Read and change kernel settings in `/proc/sys`, directly or with `sysctl`.
- Combine the module's tools (ps, pidof, kill, nice, nohup, /proc) to solve practical tasks.
Files that are not on any disk
/proc is a virtual filesystem: nothing in it is stored anywhere. When you read one of its files, the kernel generates the text on the spot from its own data structures. That is why ls -l /proc/meminfo shows a size of 0, yet cat prints a page of numbers, and why reading the same file twice can give different answers. /proc/mounts lists it as filesystem type proc. It is the kernel's window for user programs, and every tool in this module looks through it: BusyBox ps walks the numbered directories, top and uptime read /proc/loadavg, and pidof compares names found in /proc/*/stat.
One directory per process
~% sleep 800 > /dev/null &
[1] 897
~% head -7 /proc/897/status
Name: sleep
Umask: 0022
State: S (sleeping)
Tgid: 897
Ngid: 0
Pid: 897
PPid: 859
~% tr '\0' ' ' < /proc/897/cmdline; echo
sleep 800
~% readlink /proc/897/cwd
/root
~% readlink /proc/897/exe
/bin/busybox
~% ls -l /proc/897/fd
lr-x------ 1 root root 64 Oct 7 19:47 0 -> /dev/null
l-wx------ 1 root root 64 Oct 7 19:47 1 -> /dev/null
l-wx------ 1 root root 64 Oct 7 19:47 2 -> /dev/null
| Entry | What it holds |
|---|---|
status | Human-readable summary: name, state, PPid, Uid, memory, SigIgn… |
cmdline | The arguments, separated by NUL bytes (tr '\0' ' ' makes them readable) |
cwd, exe, root | Symlinks to its working directory, its program file and its root |
fd/ | One symlink per open file descriptor: 0, 1, 2 and the rest |
environ | The environment it was started with, NUL-separated |
stat | One line of raw numbers: field 6 session, field 19 nice value… |
/proc/self is a symlink that always points at the process reading it, and your shell's own directory is /proc/$. These files answer questions no other tool here can: *which directory was that job started in?* (cwd), *which file is it writing to?* (fd), *what environment did it get?* (environ). They also enforce permissions: a normal user cannot read another user's environ or fd. Directories vanish the instant the process exits.
The system files
Outside the numbered directories live the system-wide views: /proc/cpuinfo (here a single *Pentium III*), /proc/meminfo (lesson 62 reads it line by line), /proc/uptime and /proc/loadavg, /proc/version with the kernel build, /proc/mounts, /proc/partitions, and /proc/cmdline, the parameters the bootloader passed to the kernel. Module 7 opens with the friendly commands built on top of them.
/proc/sys: knobs you can turn
~% cat /proc/sys/kernel/pid_max
32768
~% cat /proc/sys/vm/swappiness
60
~% echo 30 > /proc/sys/vm/swappiness
~% sysctl vm.swappiness
vm.swappiness = 30
~% sysctl -w vm.swappiness=60
vm.swappiness = 60
Under /proc/sys most files are writable by root, and writing changes the running kernel immediately: the hostname, the maximum PID, how eagerly memory is swapped, network behaviour. sysctl is the same thing with dots instead of slashes: vm.swappiness is /proc/sys/vm/swappiness; -n prints only the value, -w writes, -a lists everything. Changes last until reboot; distributions reapply permanent ones from /etc/sysctl.conf at boot.
Module review
| Question | Tool |
|---|---|
| What is running, with which parent and state? | ps -o pid,ppid,stat,args (51-52) |
| What is eating the CPU right now? | top, top -b -n 1 (53) |
| Run, pause, resume my own work | &, Ctrl-Z, jobs, fg, bg, wait (54) |
| Stop or signal a process | kill, kill -9, kill -STOP/-CONT (55) |
| Find or signal by name | pidof, killall (56) |
| Who gets the CPU first | nice, renice (57) |
| How long did it take | time, sleep, date +%s (58) |
| Survive the terminal closing | nohup, setsid (59) |
| Everything else about a process | /proc/PID/… (60) |
Commands in this lesson
| Command | What it does |
|---|---|
cat /proc/PID/status | Readable summary of one process. |
tr '\0' ' ' < /proc/PID/cmdline | Its full command line. |
readlink /proc/PID/cwd | Its current working directory. |
ls -l /proc/PID/fd | Its open files. |
tr '\0' '\n' < /proc/PID/environ | The environment it started with. |
cat /proc/sys/kernel/pid_max | Read a kernel setting. |
sysctl -w vm.swappiness=30 | Change a kernel setting until reboot. |
Quiz
Why does `ls -l /proc/meminfo` show a size of 0?
- The file is empty until a program writes to it
- It is virtual: the kernel generates its content when it is read
- It is compressed
Which /proc entry tells you the directory a running process is working in?
- `/proc/PID/root`
- `/proc/PID/cwd`
- `/proc/PID/exe`
`echo 30 > /proc/sys/vm/swappiness` as root. How long does the change last?
- Forever
- Until the next reboot
- Until the shell exits
`ps` shows a process with STAT `SN`. What do you know?
- It is sleeping and has a positive nice value (low priority)
- It is stopped and new
- It is a zombie
You started a long command without `&`. How do you move it to the background without restarting it?
- Ctrl-C, then `bg`
- Ctrl-Z, then `bg`
- `nohup %1`
What is the right order when a process will not exit?
- `kill -9` first, TERM if that fails
- `kill` (TERM), wait and check, then `kill -9` as a last resort
- `killall -HUP` always
`time` reports real 4.0 s, user 3.9 s, sys 0.1 s. What limited the command?
- The disk
- The network
- The CPU: it was computing nearly the whole time
Which line starts a job that survives a hangup and keeps a log you chose?
- `job > log &`
- `nohup job > log 2>&1 &`
- `nice job > log &`
Practice
A `sleep 2500` was started from some directory you do not know. Read its working directory from /proc and write it (just the path) into `/root/lab/l60/cwd.txt`.
Two jobs are running: `sleep 2600` and `sleep 2601`. End `sleep 2600` politely (TERM) and give `sleep 2601` the lowest possible priority, leaving it running.
Start `sleep 2700` in the background so that it survives a hangup, runs with nice value 10, and sends its output and errors to `/root/lab/l60/job.log`.
Open this lesson in the app to do the tasks in a real Linux machine and have them checked.