Understanding Running Processes
Every program running on a Linux system is a process — an instance of a program with its own memory space, file descriptors, and execution state, tracked by the kernel under a unique PID (Process ID) assigned when it starts. Tools for inspecting running processes — a full snapshot across every user, a live continuously-updating view, or a targeted lookup by name — are all just different windows onto the same underlying kernel process table.
A process listing typically distinguishes the memory a process could theoretically use (VSZ, virtual memory size) from the memory it's actually using right now (RSS, resident set size) — a large gap between the two is normal and doesn't by itself mean anything is wrong. It also reports the process's current state: running, sleeping/idle while waiting on something, stopped, or — the one that trips people up — a zombie, a process that has already finished executing but whose exit status hasn't yet been collected by its parent, so the kernel keeps a skeleton entry around until that happens.
Signals — what they actually are
kill, despite the name, is not fundamentally a "make this process die" command — it's the general mechanism for delivering signals: asynchronous notifications the kernel sends to a process, which the process can handle, ignore, or be terminated by, depending on the specific signal and whether the program has registered its own handler for it. This is the same interrupt concept covered elsewhere in this chapter, applied to software rather than hardware — a signal interrupts whatever the process is doing to notify it that something happened.
The distinction that matters most operationally is between SIGTERM and SIGKILL. SIGTERM is a request: the kernel delivers it to the process and waits, giving the process's own code a chance to run cleanup logic — flush buffers to disk, close database connections cleanly, delete temporary files, tell an upstream that a graceful shutdown is underway. A well-behaved program can even choose to ignore SIGTERM if it needs to finish something first. SIGKILL is fundamentally different: it is never delivered to the process in any sense the process could react to. The kernel simply removes the process from existence immediately at the scheduler level — no handler runs, no cleanup happens, and whatever the process was doing is abandoned exactly where it stood. This is why standard operational discipline is to send SIGTERM first and only escalate to SIGKILL if the process fails to exit within a reasonable grace period — SIGKILL guarantees termination, but at the cost of any chance to leave things in a consistent state. It's also exactly why Kubernetes sends SIGTERM to a container and waits out a configured grace period before following up with SIGKILL: giving the application a real chance to shut down cleanly before force-killing it.
Other signals carry meaning by convention rather than hard requirement — many long-running daemons, for instance, treat SIGHUP ("hangup," historically sent when a controlling terminal disconnected) as a request to reload configuration without restarting, a convention that long outlived the literal hangups it was named after.
Foreground, background, and suspended — a process's relationship to your terminal
A shell can run a command in the foreground, where it owns your terminal until it finishes and you can't type anything else into that shell meanwhile, or in the background, where the shell starts it and immediately hands your prompt back while the process keeps running unattended. A running foreground process can also be suspended — paused in place, not terminated, still holding all of its state — and later resumed, either in the background or brought back to the foreground. This is a genuinely different operation from killing and restarting a process: a suspended process picks up exactly where it left off, mid-computation, because nothing about its state was ever destroyed.
Interviewers frequently ask: "What is the difference between kill -9 and kill -15?" The answer that impresses: SIGTERM (15) is a cooperative signal — the process receives it and can run cleanup handlers before exiting. SIGKILL (9) is handled entirely by the kernel and cannot be caught, blocked, or ignored by the process. Use SIGTERM first and give the process a few seconds; escalate to SIGKILL only if it does not respond. In containerized environments, this distinction matters for graceful shutdown — Kubernetes sends SIGTERM and waits terminationGracePeriodSeconds before sending SIGKILL.