CS 222: Operating Systems › Lesson 1 of 10

OS Concepts: Kernel, System Calls, Processes

Lesson 1 · OKSTEM College · AS Computer Science

What Does an Operating System Do?

An operating system (OS) is the software layer between hardware and user applications. It provides three fundamental services:

Common examples: Linux, macOS (XNU kernel), Windows NT, Android (Linux kernel).

Kernel vs. User Space

Modern CPUs support at least two privilege levels:

ModeWho runs hereWhat it can do
Kernel modeOS kernelFull hardware access — I/O ports, MMU, interrupts
User modeApplicationsRestricted; cannot directly access hardware

A system call is the controlled gateway from user mode to kernel mode. When a program calls read(), it triggers a software interrupt that transfers execution to the kernel, which performs the I/O and returns the result.

Trap instruction: On x86-64, syscall is the instruction that raises privilege level and jumps to the OS system call handler. On Linux, syscall numbers are defined in the kernel ABI.

Processes

A process is a running instance of a program. Each process has its own:

Process States

Process State Machine

New: Process created (fork() called). PCB allocated, memory mapped.
Ready: Loaded in memory, waiting for CPU. Multiple processes can be ready simultaneously.
Running: Currently executing on a CPU core. Only one process per core at a time.
Waiting/Blocked: Waiting for I/O, a semaphore, or a timer. Does not consume CPU.
Terminated: Process finished. Parent must call wait() to reap it; otherwise it becomes a zombie.

Process Control Block (PCB)

The kernel stores per-process state in a PCB (also called task_struct in Linux):

Context Switching

When the OS switches the CPU from process A to process B:

  1. Save all of A's registers into A's PCB.
  2. Update A's state (Running → Ready or Blocked).
  3. Select B from the ready queue.
  4. Load B's registers from B's PCB.
  5. Update B's state (Ready → Running).
  6. Jump to B's saved program counter.

Context switch overhead: Saving/restoring registers, flushing TLB entries, and cold cache effects make context switches expensive. OS schedulers minimize unnecessary switches.

Practice Problems

Problem 1 — System Call Sequence

A user program calls printf("Hello "). Trace the path from user space to the terminal display, identifying where system calls occur.

Step 1: printf() builds a formatted string in the C library buffer.
Step 2: When the buffer is flushed, the C library calls write(fd=1, buf, len) — this IS the system call.write() is syscall #1 on Linux x86-64
Step 3: CPU switches to kernel mode via syscall instruction.
Step 4: Kernel writes bytes to stdout (terminal driver → display).
One system call: write(1, "Hello ", 6). The kernel handles the terminal output. The C library buffers multiple small writes and batches them into fewer system calls for efficiency.

Problem 2 — Zombie Process

A parent process forks a child. The child exits immediately, but the parent never calls wait(). What happens? Why is this a problem?

The child becomes a zombie: it has exited but its PCB remains in the process table so the parent can retrieve the exit status. If the parent never calls wait(), the PCB is never freed. Accumulating zombies exhaust the process table, preventing new process creation.

🔄 Process State Simulator

State: NEW

Knowledge Check

What is the primary purpose of a system call?

That is inter-process communication or a library call, not a system call.
Correct — system calls are the controlled interface to the kernel.
Thread context switches may involve the kernel but the system call interface is about user→kernel privilege transition.
exec() makes a system call to load a program, but that is one use of system calls — not the definition.
📖 Quick Recap

A system call crosses the privilege boundary from user space to kernel space. Calling another program's function (same privilege level) is different.

📖 Quick Recap

A syscall is specifically about requesting kernel services (I/O, process creation, etc.). Thread switching is separate, though the kernel scheduler may be involved.

📖 Quick Recap

exec() is one system call. The definition of a system call is broader: any controlled user→kernel request for services (read, write, fork, mmap, etc.).

A process in the BLOCKED state is:

A running process is in the RUNNING state, not BLOCKED.
That is the READY state.
Correct — BLOCKED processes do not compete for CPU until the event occurs.
That describes a zombie process, which has exited.
📖 Quick Recap

RUNNING: currently executing instructions on a CPU core. BLOCKED: waiting for an event (I/O completion, semaphore signal, timer).

📖 Quick Recap

READY: in memory, waiting for a CPU to become available. BLOCKED: waiting for a non-CPU event like I/O completion.

📖 Quick Recap

A zombie is in the TERMINATED state, not BLOCKED. BLOCKED processes are still alive but paused waiting for an event.

The Process Control Block (PCB) stores:

Source code lives on disk; the PCB holds runtime state.
Correct — the PCB is the OS's per-process data structure.
PID is one field; the PCB contains much more runtime state.
Disk allocation is managed by the file system, not the PCB.
📖 Quick Recap

Source code is a file on disk. The PCB holds saved registers, memory maps, open files, PID, and scheduling info — everything the OS needs to manage and resume a process.

📖 Quick Recap

The PCB (task_struct in Linux) contains PID, PPID, state, all CPU registers, memory maps, open file descriptors, signal handlers, priority, and more.

📖 Quick Recap

File system structures (inodes, block maps) track disk usage. The PCB tracks runtime CPU and memory state.

Which of the following is NOT saved during a context switch?

The PC is saved so the process can resume at the correct instruction.
All general-purpose registers are saved in the PCB.
Correct — disk data is persistent and doesn't need to be saved during a context switch.
The page table base register is saved so memory mapping is restored.
📖 Quick Recap

The PC is one of the most critical registers to save — it holds the address of the next instruction to execute.

📖 Quick Recap

Every register must be saved: arithmetic registers, stack pointer, flags, etc. Missing one would corrupt the process's state on resume.

📖 Quick Recap

The CR3 register (x86) points to the page table. It must be saved/restored to give each process its correct address space view.

A zombie process is one that has:

Ctrl+Z sends SIGTSTP — the process is stopped, not a zombie.
Correct — zombies hold a PCB slot until wait() is called.
A segfault kills the process; whether it becomes a zombie depends on whether the parent calls wait().
High CPU usage is a runaway process, not a zombie.
📖 Quick Recap

SIGTSTP puts a process in a stopped/suspended state. A zombie has actually exited but its PCB hasn't been freed because the parent hasn't called wait().

📖 Quick Recap

A crashed process exits (possibly abnormally). If the parent never calls wait(), it becomes a zombie — but the crash itself doesn't define the zombie state.

📖 Quick Recap

A zombie has already exited — it uses no CPU at all. It only occupies a PCB entry in the process table.

Next →