Skip to content
VLSI Mentor

Linux & Bash · Part I · Module 7 · Processes, Jobs and Signals

What a Process Is

A program is a file sitting still on disk. A process is that program actually running — and a running thing needs a name, an owner, a place to work and somewhere to have come from. This chapter establishes all five, because every other chapter in this module is a consequence of them.

Intermediate16 min readLinuxPart IFundamentalsProcesses

Part I · Module 7 · Chapter 7.1 · What a Process Is

Six modules in, everything you have learned has been about things that sit still. A file sits on a disk. A directory sits above other directories. A permission bit sits in an inode. None of it moves until something makes it move.

This module is about the something.

1. A Program Is Not a Process

Start with a distinction that sounds like hair-splitting and turns out to carry the whole module.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l /bin/sleep
-rwxr-xr-x 1 root wheel 141472 Mar 28 12:49 /bin/sleep

That is a program. It is a file. It has a size, an owner, permission bits and an inode, exactly like every file in Module 5. Nothing about it is running. You could copy it, rename it, delete it. It would behave like any other file, because it is any other file — one that happens to contain machine instructions rather than text.

Now make it run:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ sleep 300 &
[1] 4821

Something new exists. It is not the file /bin/sleep; the file is still sitting there unchanged. It is a process: an instance of that program, currently executing, with state of its own that the file never had.

One program file on disk can be running as several separate processes at the same time. Each process has its own identifying number, its own working directory and its own copy of the environment, so one can be changed without affecting the other.A program on diskone file — it is not runningA running processits own number, directory andenvironmentAnother running processsame program, completely separatestatestartedstarted again12
Figure 1 — one program file can be running as several separate processes at the same time. Each process has its own identifying number, its own working directory and its own copy of the environment, so one can be changed without affecting the other. The file on disk is unchanged by any of it.

You have already met one consequence of this without the vocabulary for it. In Chapter 1.7 you learned that ls is a file on disk and cd is not. Running ls creates a process. Running cd does not — there is no program to run, so the shell does the work itself, in the process it already is. That chapter told you the split existed. This one explains what the split is.

2. The Number

The first thing a process gets is a number. The output above showed it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ sleep 300 &
[1] 4821

The 4821 is the process ID, almost always written PID. The [1] is something else entirely — a job number, which belongs to Chapter 7.5. Ignore it for now.

A PID is:

  • a plain integer, allocated by the kernel when the process starts;
  • unique among processes currently running — no two live processes share one;
  • not stable across runs. Start the same command twice and you get two different numbers. Reboot and you get different numbers again.

That last point matters more than it looks. A PID is an identifier for this particular run, not for "the simulator" or "my job". Any script that writes down a PID and uses it ten minutes later is making a bet that the process is still alive, and that bet is not always safe — numbers are reused after a process exits and the counter wraps around.

Your shell knows its own PID, and keeps it in a variable:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ echo $$
11286

$$ is the PID of the shell you are typing into. Run it again and you will get the same answer, because it is the same shell. Open a second terminal window and run it there and you will get a different one, because that is a different shell — a second process running the same program.

3. Every Process Has a Parent

Processes are not created out of nothing. Every process is started by another process, and the one that started it is its parent.

Your shell keeps that number too:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ echo $PPID
11274

$PPID is the parent process ID — the PID of whatever started your shell. On a machine you logged into over the network, that will be the login or SSH service. In a terminal application, it will be the terminal. Inside another shell, it will be that shell.

You can follow the chain by hand. Here is a real one, walked a step at a time:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ echo $$
11286

$ echo $PPID
11274

$ ps -o pid,ppid,comm -p 11286,11274
  PID  PPID COMM
11274 24759 /bin/zsh
11286 11274 bash

Read it from the bottom. The bash at PID 11286 was started by 11274. PID 11274 is a zsh, and it was started by 24759. Keep walking and the chain always ends in the same place: PID 1, the first process the kernel starts at boot, which has no parent at all.

4. What Else a Process Carries

A PID and a parent are the two identifiers. A process also carries state — things that are true of this run and nothing else. Four of them matter for everything that follows.

Its owner

A process runs as somebody. That is what makes the permission rules of Module 5 mean anything: when a process tries to open a file, the kernel compares the file's ownership and mode against the process's user, not against whoever happens to be sitting at the keyboard.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ps -o pid,user,comm -p $$
  PID USER     COMM
11286 engineer bash

A process owned by engineer can do exactly what engineer can do. No more.

Its working directory

Every process has a current working directory — the one you met in Chapter 2.3. It is not a property of your terminal or your login. It is a property of the process.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

That is your shell's working directory. A different process can be sitting somewhere else entirely at the same moment.

Its environment

Every process has an environment: a set of name-and-value pairs it was handed when it started. You have been using one all along.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ echo $HOME
/home/engineer

$ echo $PATH | tr ':' '\n' | head -3
/usr/local/bin
/usr/bin
/bin

PATH is the variable Chapter 1.7 used to explain how the shell finds ls. It is not a global setting on the machine. It is a value in your shell's environment, and each process gets its own copy. Variables are Module 8 and the environment is Module 10; the only thing needed here is that the environment belongs to the process.

Its open files

A process has a set of files it currently has open, including the three it almost always starts with — the places its input comes from and its normal and error output go to. Those three are Module 12's subject. Mentioned here only so the list is complete.

5. "Its Own Copy" Is the Important Phrase

Items 4 and 5 said its own working directory and its own copy of the environment. That wording is doing real work, and it is easiest to see by trying to break it.

Here is a small script that changes directory:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
#!/bin/bash
echo "  inside the script, PID $$, parent $PPID"
echo "  it started in: $(pwd)"
cd /home/engineer/project/rtl
echo "  it moved to:   $(pwd)"

Run it from your shell:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ./cdthere.sh
  inside the script, PID 12545, parent 12537
  it started in: /home/engineer/project
  it moved to:   /home/engineer/project/rtl

$ pwd
/home/engineer/project

The script genuinely changed directory. It printed the proof — it really was in rtl. And then it ended, and your shell is exactly where it was.

Nothing went wrong. The script ran as its own process, PID 12545, whose parent was your shell at 12537. It got its own copy of the working directory, changed its own copy, and then exited, taking its copy with it. Your shell's copy was never touched.

The same thing happens to the environment:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ export PROJECT=/home/engineer/project

$ bash -c 'echo "  child sees PROJECT=$PROJECT"; PROJECT=/tmp/changed; echo "  child changed it to $PROJECT"'
  child sees PROJECT=/home/engineer/project
  child changed it to /tmp/changed

$ echo "parent still has PROJECT=$PROJECT"
parent still has PROJECT=/home/engineer/project

The child inherited the value — it could see /home/engineer/project without being told. Then it changed it, successfully, for itself. And the parent was unaffected.

6. Two Runs Are Two Processes

Figure 1 claimed that one program can be several independent processes. That is worth seeing rather than taking on trust.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ sleep 300 &
[1] 4821

$ sleep 300 &
[2] 4822

$ ps -o pid,ppid,etime,comm -p 4821,4822
  PID  PPID     ELAPSED COMM
 4821 11286       00:09 sleep
 4822 11286       00:04 sleep

Two PIDs. The same parent — your shell started both. The same program, /bin/sleep, loaded twice. Different elapsed times, because they started four seconds apart.

Kill one and the other carries on, because they share nothing except the file they were loaded from:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ kill 4821

$ ps -o pid,comm -p 4821,4822
  PID COMM
 4822 sleep

This is the entire reason a regression can run forty simulations at once. They are forty processes, each with its own PID, its own working directory and its own copy of the environment, all loaded from the same simulator binary. The binary does not need to be forty times as big, and the forty runs cannot tread on each other's state — because there is no shared state to tread on.

7. A First Look at the Whole List

The command that shows processes gets a chapter of its own next. For now, one look at its output, to see the five facts in a real listing:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ps -ef | head -3
  UID   PID  PPID   C STIME TTY          TIME CMD
    0     1     0   0 Mar28 ?        123:17.90 /sbin/init
  501   208     1   0 Sep28 ?          0:00.13 /usr/bin/some-service

Three of the five facts are columns:

  • UID — the owner, as a number rather than a name.
  • PID — the process's own number.
  • PPID — its parent's number.

And look at the first row. PID 1, PPID 0 — the process with no parent, exactly as described in §3. Every other row on the machine descends from it.

The remaining columns (C, STIME, TTY, TIME, CMD) are Chapter 7.2's subject.

8. Why the Model Matters

It is worth being explicit about what this buys you, because the payoff arrives over the next seven chapters rather than in this one.

Question you will haveAnswer from the model
Why can't my script change my directory?It is a separate process with its own copy. §5.
Why does the same command appear eleven times in ps?Eleven processes, one program. §6.
Which of these two simulations is mine?Compare the UID column — the owner is per-process. §4.
Why did my job die when I closed the terminal?The terminal was an ancestor. 7.8.
Why is this process still running after I killed its parent?A dead parent does not kill a child. 7.4, 7.7.
Why did pressing Ctrl-C do nothing?A signal is a request. 7.6.

Every one of those is a question engineers ask on a shared machine, and every one has a short answer once the five facts are in place.

Practice

Do these in order, in a scratch directory. Each one takes under a minute and each one proves a claim from the chapter rather than merely repeating it.

1 — Find your own shell and its parent.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
echo "this shell is PID $$, started by $PPID"
ps -o pid,ppid,user,comm -p $$

2 — Walk the chain to PID 1. Take the PPID you just saw and look it up; take its PPID and look that up; keep going. Count the steps. You should reach 1 in somewhere between two and six hops.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ps -o pid,ppid,comm -p <the PPID you saw>

3 — Prove a child cannot change your directory. Write the script from §5, run it, and compare pwd before and after. Then note what the script's $PPID was and confirm it equals your shell's $$.

4 — Prove two runs are independent. Start two sleep 300 & jobs. Confirm with ps that they have different PIDs and the same PPID. Kill one. Confirm the other survives.

5 — Prove the environment is copied, not shared. Export a variable, start bash as a child, change the variable inside the child, exit, and check the value in the parent.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
export MARKER=original
bash          # now inside a child shell
echo $MARKER  # shows: original  (inherited)
MARKER=changed
exit          # back in the parent
echo $MARKER  # shows: original  (unaffected)

6 — Count what is running. Run ps -e | wc -l. Most people are surprised by how large the number is on an idle machine — a few hundred is normal. Almost none of them are yours.

Check Your Understanding

1. You run wc -l report.txt twice in a row. How many processes were created, and do they have the same PID?

2. A colleague says "I deleted the simulator binary, so the running simulation will stop." Using the program-versus-process distinction, is that right?

3. Your shell is PID 11286. A script you run reports $$ as 12545 and $PPID as 11286. What does that tell you about where the script came from?

4. Inside a script you write cd /tmp and then export RESULTS=/tmp/out. After the script finishes, your shell is still in your project directory and echo $RESULTS prints nothing. Which of these two outcomes is a bug?

5. ps -ef shows a row with PID 1 and PPID 0. Why is this the only row on the machine that can look like that?

9. Remember

  • A program is a file; a process is a running program. Almost every confusing question about processes dissolves once that sentence is in place.
  • Every process has a PID — a number naming this run, unique among live processes, not stable across runs and eventually reused.
  • $$ is your shell's PID. $PPID is its parent's. Both are available in any shell, instantly.
  • Every process has exactly one parent, and the chain always terminates at PID 1, which the kernel starts at boot and which has no parent of its own.
  • A process carries five things: a PID, a parent, an owner, a working directory and an environment.
  • A child gets a copy of the parent's working directory and environment. It can change its copy freely. The parent's is untouched.
  • Inheritance flows downward only. There is no mechanism for a child to modify its parent — which is the complete answer to "why didn't my script change my directory?"
  • Permissions are checked against the process's owner, which is what connects Module 5 to everything running on the machine.
  • One program, many processes. Running the same binary forty times gives forty independent processes that share nothing but the file they were loaded from.

The next chapter puts this to work. Knowing that a process has an owner, a parent, a start time and a command line is only useful if you can find the one you care about among the several hundred that are running — which is what ps and pgrep are for.

Where this fits

Part of the Linux & Bash curriculum.