wisconsin
Lecture 2 - Processes: Virtualizing the CPU

Lecture 2 - Processes: Virtualizing the CPU

Curated by Last modified: 8 min read

Instructor: Michael Swift & Tej Chajed Topics: Processes, process state, CPU virtualization, limited direct execution, context switching


What is a Process?

Process: An execution stream in the context of a process state.

Execution stream: A stream of executing instructions; a running piece of code; a “thread of control.”

Process state: Everything that the running code can affect or be affected by.

Process state includes:

  • Registers — general purpose, floating point, status, program counter, stack pointer
  • Address space — heap, stack, and code
  • Open files

A process is different from a program:

  • Program: Static code and static data (lives on disk)
  • Process: Dynamic instance of code and data (lives in memory)

Can have multiple process instances of the same program (e.g., many users running ls at the same time).


Process Creation

Process Creation:

  1. Program sits on disk (code + static data)
  2. OS loads code and static data into memory
  3. OS allocates heap and stack in the address space
  4. Process is ready to execute

Two Ways to Create a Process

  1. Build a new empty process from scratch
  2. Copy an existing process and change it appropriately

Option 1: New Process from Scratch

  • Steps:
    • Load specified code and data into memory; create empty call stack
    • Create and initialize PCB (make look like context-switch)
    • Put process on ready list
  • Advantages: No wasted work
  • Disadvantages: Difficult to setup process correctly and to express all possible options
    • Process permissions, where to write I/O, environment variables
    • Example: Windows has call with 10 arguments

Option 2: Clone Existing Process and Change

  • Example: Unix fork() and exec()
    • fork(): Clones calling process
    • exec(char *file): Overlays file image on calling process
  • fork():
    • Stop current process and save its state
    • Make copy of code, data, stack, and PCB
    • Add new PCB to ready list
  • exec(char *file):
    • Replace current data and code segments with those in specified file
  • Advantages: Flexible, clean, simple
  • Disadvantages: Wasteful to perform copy and then overwrite memory

Unix Shell Implementation

while (1) {
    char *cmd = getcmd();
    int retval = fork();
    if (retval == 0) {
        // This is the child process
        // Setup the child's process environment here
        // E.g., where is standard I/O, how to handle signals?
        exec(cmd);
        // exec does not return if it succeeds
        printf("ERROR: Could not execute %s\n", cmd);
        exit(1);
    } else {
        // This is the parent process; Wait for child to finish
        int pid = retval;
        wait(pid);
    }
}

Virtualizing the CPU

Goal: Give each process the impression it alone is actively using the CPU.

ResourceSharing Strategy
CPUTime sharing
MemorySpace sharing (later)
DiskSpace sharing (later)

Lecture Note

Time sharing on the physical CPU means processes take turns: A, B, A, B, A… Each process thinks it has its own virtual CPU. Memory and disk use space sharing — each process gets its own region.

Process States

stateDiagram-v2
    running --> ready : deschedule
    ready --> running : schedule
    running --> blocked : I/O issued
    blocked --> ready : I/O complete
  • Running: On the CPU (only one on a uniprocessor)
  • Ready: Waiting for the CPU
  • Blocked: Asleep — waiting for I/O or synchronization to complete

Lecture Note

When B is running, A sits in the ready state. The scheduler picks from the ready queue.

OS must track every process in the system:

  • Each process identified by unique Process ID (PID)

OS maintains queues of all processes:

  • Ready queue: Contains all ready processes
  • Event queue: One logical queue per event
    • e.g., disk I/O and locks
    • Contains all processes waiting for that event to complete

Limited Direct Execution

Direct Execution

  • Allow user process to run directly on hardware
  • OS creates process and transfers control to starting point (i.e., main())

Problems with Direct Execution

  1. Process could do something restricted — could read/write other process data (disk or memory)
  2. Process could run forever (slow, buggy, or malicious) — OS needs to be able to switch between processes
  3. Process could do something slow (like I/O) — OS wants to use resources efficiently and switch CPU to other process

Solution: Limited direct execution — OS and hardware maintain some control.


Problem 1: Restricting Execution

How can we ensure user process can’t harm others?

Solution: privilege levels supported by hardware (bit of status)

  • User processes run in user mode (restricted mode)
  • OS runs in kernel mode (not restricted)
    • Instructions for interacting with devices
    • Could have many privilege levels (advanced topic)

How can a process access a device?

  • System calls (function call implemented by OS)
  • Change privilege level through syscall trap instruction

What User Processes Cannot Do

User processes are not allowed to perform:

  • General memory access
  • Disk I/O
  • Special x86 instructions like lidt

If a process tries to do something restricted, the hardware generates a fault/exception.

How System Calls Work

  1. Process P wants to call read() — but P can only see its own memory because of user mode (other areas, including kernel, are hidden)
  2. P cannot call kernel code directly — instead it uses a syscall trap instruction
  3. The read() library function executes: movl $6, %eax; syscall
    • $6 is the syscall-table index identifying which system call to invoke
    • syscall is the trap instruction that calls through the trap table
  4. The syscall instruction switches to kernel mode — now the kernel can access all memory
  5. The kernel follows entries in the trap table to the correct system call handler (e.g., sys_read)
  6. The kernel can access user memory to fill in the user buffer
  7. Return-from-trap at end to return to Process P (back in user mode)

Problem 2: How to Take CPU Away?

OS requirements for multiprogramming (or multitasking):

  • Mechanism — to switch between processes
  • Policy — to decide which process to schedule when

Separation of Policy and Mechanism

Reoccurring theme in OS:

  • Policy: Decision-maker to optimize some workload performance metric
    • Which process when?
    • Process Scheduler (future lecture)
  • Mechanism: Low-level code that implements the decision
    • How?
    • Process Dispatcher (this lecture)

Dispatch Mechanism

OS runs a dispatch loop:

while (1) {
    run process A for some time-slice
    stop process A and save its context
    load context of another process B
}

Lecture Note

The stop + save + load is called a context switch. Each process runs for a time slice (e.g., A, B, A, B…).

Two key questions:

  1. How does the dispatcher gain control?
  2. What execution context must be saved and restored?

Q1: How Does the Dispatcher Get Control?

Option 1: Cooperative Multi-tasking

  • Trust process to relinquish CPU to OS through traps
    • Examples: System call, page fault (access page not in main memory), or error (illegal instruction or divide by zero)
    • Provide special yield() system call
  • Problem: Processes can misbehave
    • By avoiding all traps and performing no I/O, can take over entire machine
    • Only solution: Reboot!
  • Not performed in modern operating systems

Option 2: True Multi-tasking

  • Guarantee OS can obtain control periodically
  • Enter OS by enabling periodic alarm clock
    • Hardware generates timer interrupt (CPU or separate chip)
    • Example: Every 10ms
  • User must not be able to mask timer interrupt
  • Dispatcher counts interrupts between context switches
    • Example: Waiting 20 timer ticks gives 200 ms time slice
    • Common time slices range from 10 ms to 200 ms

Q2: What Context Must Be Saved?

Dispatcher must track context of process when not running:

  • Save context in process control block (PCB) (or, process descriptor)

What information is stored in PCB:

  • PID
  • Process state (i.e., running, ready, or blocked)
  • Execution state (all registers, PC, stack ptr)
  • Scheduling priority
  • Accounting information (parent and child processes)
  • Credentials (which resources can be accessed, owner)
  • Pointers to other allocated resources (e.g., open files)

Lecture Note

The PCB is a struct (e.g., struct proc { pid, status, ... }) that holds everything the OS needs to know about a process.

Requires special hardware support:

  • Hardware saves process PC and PSR on interrupts

Context Switch Procedure

sequenceDiagram
    participant Program as Program
    participant HW as Hardware
    participant OS as Operating System

    Note over Program: Process A running...
    HW->>HW: timer interrupt
    HW->>HW: save regs(A) to k-stack(A)
    HW->>HW: move to kernel mode
    HW->>OS: jump to trap handler
    OS->>OS: Handle the trap
    OS->>OS: Call switch() routine
    OS->>OS: save regs(A) to proc-struct(A)
    OS->>OS: restore regs(B) from proc-struct(B)
    OS->>OS: switch to k-stack(B)
    OS->>HW: return-from-trap (into B)
    HW->>HW: restore regs(B) from k-stack(B)
    HW->>HW: move to user mode
    HW->>Program: jump to B's IP
    Note over Program: Process B running...

Lecture Note

A timer interrupt (or syscall trap) causes hardware to save registers to the kernel stack and switch to kernel mode. The OS then performs a software context switch — saving A’s registers to A’s PCB and restoring B’s from B’s PCB. Finally, return-from-trap restores B’s registers from B’s kernel stack and jumps to B in user mode.


Summary

  • Virtualization: Context switching gives each process the impression it has its own CPU
  • Direct execution makes processes fast
  • Limited execution at key points ensures OS retains control
  • Hardware provides a lot of OS support:
    • User vs kernel mode (privilege bit)
    • Timer interrupts
    • Automatic register saving and return-from-trap

Linked to this page