Memra

Inspecting processes with ps and top

◈ 10 cards

Choosing between the System V and BSD ps dialects, decoding a STAT string one character at a time, and using top to watch it move.

Two dialects, one command

ps grew up twice, and modern Linux accepts both grammars. The rule that saves you is simple: options with a leading hyphen are System V; options with no hyphen are BSD. They are not interchangeable, and mixing them gives you a third, ill-defined thing.

  • ps -ef — System V style. Every process (-e) in full format (-f). Columns: UID PID PPID C STIME TTY TIME CMD.
  • ps aux — BSD style. All users' processes (a), including those with no controlling terminal (x), in user format (u). Columns: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND.

They are not the same listing with different headers. -ef gives you PPID and aux does not; aux gives you STAT, VSZ and RSS and -ef does not. Choose by the question you are asking: who is this process's parent? is -ef; what state is it in and how much memory is it holding? is aux.

If neither fits, stop guessing and ask for exactly the columns you want:

ps -o pid,ppid,ni,pri,stat,rss,comm

-o prints only the named keywords, in the order given, and it works the same way on Linux, BSD and Solaris — which makes it the portable answer and the one worth memorising.

Reading a STAT string

The STAT column packs several facts into a few characters. The first character is the state; every character after it is a flag. Decode left to right:

States: R runnable (running or ready) · S sleeping, interruptibly · D in an uninterruptible wait, almost always disk I/O · T stopped, by Ctrl-Z or SIGSTOP · Z zombie · I idle (Linux: an idle kernel thread; BSD: sleeping more than 20 seconds).

Flags: + in the foreground process group · s a session leader · < raised scheduling priority · N lowered scheduling priority (niced) · l multi-threaded.

So:

  • Ss — sleeping, and a session leader. Your login shell, waiting for you to type.
  • S+ — sleeping, in the foreground. A less waiting for a keypress.
  • R+ — runnable, in the foreground. The command you are watching right now.
  • TN — stopped and niced. Something you suspended after renicing it.
  • Z — a zombie, and nothing else, because a zombie has no context left to describe.

Worked example — decoding one listing

USER  PID  %CPU %MEM   VSZ  RSS TTY  STAT START TIME COMMAND
you  2110  0.0  0.1  9420 4356 pts/0 Ss   09:14 0:00 -bash
you  4802 98.6  2.4 512300 96120 pts/0 R+  10:02 1:47 ./mandelbrot
you  4803  0.0  0.0     0    0 pts/0 Z    10:02 0:00 [helper] <defunct>

Read it line by line. PID 2110 is your login shell: Ss says sleeping session leader, and the leading - on -bash is the conventional mark of a login shell. PID 4802 is doing real work: R+ says runnable and in the foreground, and it is holding 96 MB resident out of a 512 MB virtual image. PID 4803 is a zombie: Z, [helper] <defunct>, 0.0 CPU and zero memory. It is not stuck and killing it does nothing — it is a receipt waiting to be collected. It will vanish when its parent calls wait(), or when its parent dies and init adopts it.

VSZ versus RSS is worth being precise about, because it is a favourite short question. VSZ is the size of the entire virtual address space in kilobytes — all mapped code, data, stack, shared libraries and unused reservations. RSS is the resident set size: the part actually in physical RAM right now. VSZ is what the process could touch; RSS is what it is costing you. VSZ can be enormous and mean nothing.

top — the same data, moving

ps is a snapshot; top redraws every second or so and sorts by CPU. Its header gives you load averages, a process count broken down by state (running / sleeping / stopped / zombie — a useful zombie alarm), CPU percentages, and memory totals. Below that, one line per process with PR/NI, VIRT and RES (the same idea as VSZ and RSS), state, and command.

Useful keys: k kill a process by PID, r renice one, u restrict to one user, M sort by memory, P sort by CPU, 1 expand per-core statistics, q quit. Solaris top and prstat bind several of these differently, so check before you press k on a machine you do not know.

Fact you wantps -ef (System V)ps aux (BSD)ownerUIDUSERprocess idPIDPIDparent pidPPIDnot shownstatenot shownSTATmemorynot shownVSZ and RSScommandCMDCOMMANDA leading hyphen is System V; no hyphen is BSD. Do not mix them.
Same moment, two conventions. Neither is a superset of the other — that is why -o exists.
STATFirst char = stateRest = flagsSsS sleepings session leaderS+S sleeping+ foreground groupR+R runnable+ foreground groupTNT stopped by Ctrl-ZN niced, lower priorityDD uninterruptible disk wait-ZZ zombie, exited, unreaped-kill cannot remove a Z. Only the parent wait() can.
First character is the state. Everything after it is a flag, and a zombie has no flags because it has no context left.
NORMAL ~/memra/learn/comp-325/inspecting-processes-with-ps-and-top utf-8 LF