Reading · Computer Systems
How a computer starts; processes and threads
The boot relay from firmware to your shell, where PID 1 fits in, what a process owns, how fork, copy-on-write and exec run every command you type, and what threads share.
The practical sessions start at the shell prompt. This reading fills in what happens before it: how a computer gets from the power button to a running system, and what the things you list with ps actually are. Two ideas from here come up in the theory tests again and again – the boot sequence, and the difference between a process and a thread.
In two lines: booting is a relay – firmware → bootloader → kernel → init → login → your session, each stage starting the next. A process is a program running in its own protected memory; threads are several flows of execution inside one process, sharing that memory.
From the power button to a prompt
1. Firmware: UEFI or BIOS
When you press the power button no operating system is running yet; the code that runs first is the firmware stored on the motherboard – UEFI on modern machines, BIOS on older ones. It initialises and checks the hardware it needs: CPU, RAM, graphics, storage. For RAM this can include memory training, where the firmware tunes the timing of the memory modules. If something fails here, there is no screen to print an error on yet, so the board reports it with an error code, an LED or a pattern of beeps.
2. Boot device and bootloader
Based on its configuration (the boot order), the firmware looks for a device the operating system can be started from. On a UEFI machine this is usually an EFI bootloader on the SSD – GRUB for many Linux systems, the Windows Boot Manager for Windows. The bootloader's single job is to load the operating system's kernel into memory and start it. It is also where a dual-boot menu lets you choose which system to start.
3. Kernel
The kernel takes control of the machine. It initialises the hardware, loads the drivers (on Linux: kernel modules) and sets up the core services of the operating system: memory management, processes and scheduling, file systems, networking. Then it starts the first program that runs outside the kernel, in user space.
4. init / systemd – PID 1
On Linux that first program is init – on most current distributions, systemd. In the classic Unix model init has PID 1, and systemd runs as PID 1 too. It starts the rest of the system as services (daemons): networking, the SSH server, logging, the services a graphical desktop needs, and many more background processes.
$ ps -p 1 -o pid,comm
PID COMMAND
1 systemd5. Login
The system reaches a login screen or prompt. You authenticate, and the system starts the processes your session needs.
6. Desktop environment – or a shell
On a graphical Linux system a desktop environment such as GNOME or KDE Plasma starts: windows, a panel, a file manager – the place where you click and start applications, with more user and system processes starting in the background. A server like the course server usually has no desktop at all. There the session is a shell, started for you by the SSH server when you log in.
Where your shell comes from
Every process except PID 1 was started by another process, its parent. So the shell you type into on the course server is the end of a chain that starts at systemd (Fig. 2).
$$ holds the PID of the current shell; ps -o pid,ppid,comm shows each process with its parent's PID (PPID). pstree, where installed, draws the chain:
$ echo $$ # the PID of your shell
24518
$ pstree -s -p $$ # its ancestors, up to PID 1 (if pstree is installed)
systemd(1)───sshd(912)───sshd(24511)───sshd(24517)───bash(24518)───pstree(24690)$ ps -o pid,ppid,comm
PID PPID COMMAND
24518 24517 bash
24702 24518 psNote that ps itself shows up as a child of bash: it's a process you just started. That is the topic of the next sections.
Processes
A process is a running program together with its own, isolated execution environment: its own virtual address space, its own resources (open files, current directory, environment variables) and a process identifier, the PID. Two processes running the same program – two shells, say – are still two processes with separate memory.
"Virtual" means each process sees memory addresses of its own, as if it had the whole memory to itself. The hardware (the MMU) and the kernel map those addresses to physical RAM, and one process can't reach another's memory by default. That isolation is why a crashing program doesn't take the others down.
Creating a process: fork()
On POSIX systems (Linux, macOS, the Unixes) the classic way to create a process is the fork() system call. The calling process gets a child: an almost exact copy of itself with a new PID. Both continue from the same point; fork() returns 0 in the child and the child's PID in the parent, which is how each knows which one it is.
A copy of the whole memory sounds expensive, and it would be. It doesn't happen: modern systems use copy-on-write (COW). Parent and child initially share the physical memory pages, marked read-only; a page is really copied only when one of them writes to it.
Running another program: exec
fork() gives you a copy of the same program. To run a different one, the child calls one of the exec functions, which replace the program in the process – code, data, stack – with a new one, while the PID stays. Every time you type a command, the shell does exactly this:
This also explains two things from the practical sessions. A script run as ./script.sh runs in a child process, so its cd or variable changes vanish when it ends – while source script.sh runs it in your current shell. And $? is simply the exit status the parent received from wait().
Threads
A thread is a unit of execution inside a process. One process can run several threads, in parallel on several CPU cores or interleaved on one. The threads share the address space and most resources of their process – code, heap, global variables, open files – so creating one doesn't involve setting up a new address space.
What each thread has of its own is its execution state: its own stack, its own register values and its own program counter (instruction pointer) – the place in the code where it currently is. A program can start several threads and give each a different job: one waits for the network, one does the calculation, one keeps the user interface responsive.
| Process | Thread |
|---|---|
| An independent execution environment | A unit of execution inside a process |
| Its own virtual address space | Shares the process's address space |
| Stronger isolation | Easier communication |
| Usually more expensive to create | Usually cheaper to create |
| Its own PID | Its own execution state and thread ID |
| Can't see another process's memory by default | Sees the process's shared memory |
An analogy: a process is a separate office with its own room and equipment. Threads are people working in the same office – they use the shared equipment, but each has a task of their own and knows where they are in it.
Seeing threads on Linux
A shell has a single thread; a browser or a database server has dozens. Linux calls threads lightweight processes (LWP):
$ ps -o pid,nlwp,comm -p $$ # NLWP = number of threads
PID NLWP COMMAND
24518 1 bash
$ grep Threads /proc/$$/status
Threads: 1
$ ps -eLf | head -5 # one row per thread (LWP = thread id)and the services systemd started
systemctl list-units --type=service --state=running # what systemd started
journalctl -b | head # the log of this boot (may need permissions)Terms
- firmware
- Code on the motherboard (UEFI or BIOS) that runs first, checks the hardware and starts a bootloader.
- bootloader
- A small program (e.g. GRUB) that loads the kernel into memory and starts it.
- kernel
- The core of the operating system: hardware, memory, processes, file systems, network.
- PID 1
- The first user-space process –
initorsystemd– ancestor of all others. - daemon
- A background service, usually started by PID 1 (sshd, cron, journald).
- process
- A running program with its own virtual address space, resources and PID.
- thread
- A flow of execution inside a process, with its own stack and registers.
- fork()
- Creates a child process as a copy of the caller.
- copy-on-write
- Pages are shared after fork and copied only when written.
- exec
- Replaces the program running in a process; the PID stays.
Summary
- Booting is a relay: firmware → bootloader → kernel → init/systemd (PID 1) → login → shell or desktop.
- Every process has a parent; your shell's chain ends at PID 1 – check it with
pstree -s $$. - A process owns a virtual address space, resources and a PID, isolated from other processes.
fork()copies a process (lazily, with copy-on-write),execswaps its program,wait()collects its exit status – the shell does all three for every command.- Threads share their process’s memory and files; each has its own stack, registers and program counter.