Operating Systems Overview and Processes

Learning Objectives

By the end of this reading, you will be able to:

  • Understand the fundamental role and responsibilities of an operating system
  • Explain the concept of a process and how it differs from a program
  • Describe the different process states and their transitions
  • Understand the Process Control Block (PCB) and its components
  • Explain context switching and its performance implications
  • Understand process creation and termination mechanisms

Table of Contents

  1. Introduction to Operating Systems
  2. What is a Process?
  3. Process States
  4. Process Control Block (PCB)
  5. Context Switching
  6. Process Creation and Termination
  7. Process Scheduling
  8. Exercises
  9. Summary

Introduction to Operating Systems

An Operating System (OS) is the most important software that runs on a computer. It manages all hardware and software resources and provides common services for computer programs.

Key Responsibilities of an Operating System

  1. Process Management: Creating, scheduling, and terminating processes
  2. Memory Management: Allocating and deallocating memory space
  3. File System Management: Organizing and managing files on storage devices
  4. Device Management: Managing device communication via drivers
  5. Security and Access Control: Protecting resources from unauthorized access
  6. User Interface: Providing CLI or GUI for user interaction

OS Architecture Layers

+----------------------------------+
|        User Applications         |
+----------------------------------+
|        System Programs           |
+----------------------------------+
|     Operating System Kernel      |
|  +----------------------------+  |
|  | Process | Memory | File   |  |
|  | Manager | Manager| System |  |
|  +----------------------------+  |
|  |    Device Drivers          |  |
|  +----------------------------+  |
+----------------------------------+
|           Hardware               |
+----------------------------------+

Operating System Types

  • Batch OS: Executes jobs in batches without user interaction
  • Time-Sharing OS: Allows multiple users to share system resources
  • Distributed OS: Manages a group of independent computers
  • Real-Time OS: Guarantees processing within strict time constraints
  • Embedded OS: Designed for embedded computer systems

What is a Process?

A process is a program in execution. While a program is a passive entity (code stored on disk), a process is an active entity with a program counter and associated resources.

Program vs Process

PROGRAM (Static)              PROCESS (Dynamic)
+------------------+          +------------------+
| Executable File  |          | Memory Space     |
| (on disk)        |   -->    | - Code Section   |
| - Instructions   |          | - Data Section   |
| - Data           |          | - Stack          |
|                  |          | - Heap           |
+------------------+          +------------------+
                              | CPU State        |
                              | - Program Counter|
                              | - Registers      |
                              +------------------+
                              | OS Resources     |
                              | - Open Files     |
                              | - I/O Devices    |
                              +------------------+

Process Memory Layout

High Memory
+------------------+
|      Stack       |  <-- Local variables, function calls
|        ↓         |
|                  |
|   Free Space     |
|                  |
|        ↑         |
|      Heap        |  <-- Dynamic memory allocation
+------------------+
|   Data Segment   |  <-- Global/static variables
| (Initialized)    |
+------------------+
|   BSS Segment    |  <-- Uninitialized data
+------------------+
|   Text Segment   |  <-- Program code (instructions)
+------------------+
Low Memory

Process Components

  1. Text Section: The executable code
  2. Data Section: Global and static variables
  3. Heap: Dynamically allocated memory during runtime
  4. Stack: Temporary data (function parameters, return addresses, local variables)
  5. Program Counter: Address of the next instruction to execute
  6. Registers: Current activity represented by register values

Process States

A process transitions through several states during its lifetime.

The Five-State Process Model

                 +-----------+
                 |           |
    New          |   New     |
    Process ---> |           |
                 +-----------+
                      |
                      | Admitted
                      v
                 +-----------+      Interrupt      +-----------+
                 |           | <------------------ |           |
                 |   Ready   |                     |  Running  |
                 |           | -----------------> |           |
                 +-----------+    Scheduler        +-----------+
                   ^    ^          Dispatch              |
                   |    |                                |
         I/O or    |    | I/O or Event                  | Exit
         Event     |    | Completion                     |
         Wait      |    |                                v
                   |    |                          +-----------+
                 +-----------+                     |           |
                 |           |                     | Terminated|
                 |  Waiting  |                     |           |
                 |  (Blocked)|                     +-----------+
                 +-----------+

State Descriptions

  1. New: Process is being created
  2. Ready: Process is waiting to be assigned to a processor
  3. Running: Instructions are being executed
  4. Waiting (Blocked): Process is waiting for some event to occur (I/O completion, signal)
  5. Terminated: Process has finished execution

State Transitions

  • New → Ready: Process creation is complete, ready to run
  • Ready → Running: Scheduler selects this process
  • Running → Ready: Time quantum expires (preemption)
  • Running → Waiting: Process requests I/O or waits for event
  • Waiting → Ready: I/O completes or event occurs
  • Running → Terminated: Process completes execution

Process Control Block (PCB)

The Process Control Block (also called Task Control Block) is a data structure maintained by the OS for every process. It contains all information about a process.

PCB Structure

+--------------------------------+
|   Process Control Block (PCB)  |
+--------------------------------+
| Process ID (PID)        : 1234 |
| Process State           : Ready|
| Program Counter         : 0x7F |
| CPU Registers           : {...}|
| CPU Scheduling Info:           |
|   - Priority            : 5    |
|   - Time Quantum        : 20ms |
| Memory Management Info:        |
|   - Base Register       : 0x0  |
|   - Limit Register      : 0xFF |
|   - Page Table Pointer  : 0xA0 |
| Accounting Info:               |
|   - CPU Time Used       : 150ms|
|   - Time Limits         : 1000 |
| I/O Status Info:               |
|   - List of Open Files  : [...] |
|   - I/O Devices Allocated:[...] |
| Parent Process ID       : 1000 |
| Child Process IDs       : [...] |
+--------------------------------+

PCB Components in Detail

  1. Process Identification

    • Process ID (PID): Unique identifier
    • Parent Process ID (PPID): ID of the process that created this one
    • User ID: Owner of the process
  2. Process State Information

    • Current state (New, Ready, Running, Waiting, Terminated)
    • Program Counter: Address of next instruction
    • CPU Registers: Accumulator, index registers, stack pointers, general-purpose registers
  3. Process Control Information

    • Scheduling priority
    • Pointers to scheduling queues
    • CPU time used
    • Time limits
    • Account numbers
  4. Memory Management Information

    • Base and limit registers
    • Page tables or segment tables
    • Memory limits
  5. I/O Status Information

    • List of open files
    • List of I/O devices allocated

Context Switching

Context switching is the mechanism where the CPU switches from one process to another. This involves saving the state of the old process and loading the saved state of the new process.

Context Switch Process

Process P1 Running                        Process P2 Running
+----------------+                        +----------------+
|   Executing    |                        |   Executing    |
|   P1 Code      |                        |   P2 Code      |
+----------------+                        +----------------+
        |                                          ^
        | Interrupt or                             |
        | System Call                              |
        v                                          |
+----------------+                                 |
| Save P1 State  |                                 |
| to PCB1        |                                 |
+----------------+                                 |
        |                                          |
        v                                          |
+----------------+                                 |
|   Scheduler    |                                 |
| Selects P2     |                                 |
+----------------+                                 |
        |                                          |
        v                                          |
+----------------+                                 |
| Restore P2     |                                 |
| State from PCB2|                                 |
+----------------+---------------------------------+

Context Switch Steps

  1. Save Context of Process P1

    • Save program counter
    • Save CPU registers
    • Save process state
    • Update PCB1
  2. Update Process State

    • Change P1 state (Running → Ready or Waiting)
    • Change P2 state (Ready → Running)
  3. Select Next Process (P2)

    • Scheduler chooses next process from ready queue
  4. Restore Context of Process P2

    • Load program counter from PCB2
    • Load CPU registers from PCB2
    • Update memory management unit
  5. Resume Execution

    • CPU begins executing P2

Context Switch Overhead

Context switching is pure overhead because the system does no useful work while switching. The time depends on:

  • Hardware support (some processors have multiple register sets)
  • Memory speed
  • Number of registers to save/restore
  • Cache invalidation

Typical context switch time: 1-10 microseconds

Process Creation and Termination

Process Creation

Operating systems create processes through system calls. In Unix/Linux, the primary mechanism is the fork() system call.

Process Creation Tree

                    init (PID 1)
                         |
        +----------------+----------------+
        |                |                |
      login           daemon1          daemon2
      (PID 50)        (PID 75)         (PID 80)
        |
     shell
    (PID 100)
        |
    +---+---+
    |       |
  gcc      ls
(PID 200) (PID 201)

Process Creation in Unix/Linux (fork)

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
    pid_t pid;

    printf("Before fork: PID = %d\n", getpid());

    pid = fork();  // Create a new process

    if (pid < 0) {
        // Fork failed
        fprintf(stderr, "Fork failed\n");
        return 1;
    }
    else if (pid == 0) {
        // Child process
        printf("Child process: PID = %d, Parent PID = %d\n",
               getpid(), getppid());
        printf("Child: Value of pid = %d\n", pid);
    }
    else {
        // Parent process
        printf("Parent process: PID = %d\n", getpid());
        printf("Parent: Child's PID = %d\n", pid);
        printf("Parent: Value of pid = %d\n", pid);
    }

    printf("Common code: PID = %d\n", getpid());

    return 0;
}

Output Example:

Before fork: PID = 1234
Parent process: PID = 1234
Parent: Child's PID = 1235
Parent: Value of pid = 1235
Common code: PID = 1234
Child process: PID = 1235, Parent PID = 1234
Child: Value of pid = 0
Common code: PID = 1235

Process Creation in Python

import os
import sys

def main():
    print(f"Before fork: PID = {os.getpid()}")

    pid = os.fork()

    if pid < 0:
        # Fork failed
        print("Fork failed", file=sys.stderr)
        sys.exit(1)
    elif pid == 0:
        # Child process
        print(f"Child process: PID = {os.getpid()}, Parent PID = {os.getppid()}")
        print(f"Child: Value of pid = {pid}")
    else:
        # Parent process
        print(f"Parent process: PID = {os.getpid()}")
        print(f"Parent: Child's PID = {pid}")
        print(f"Parent: Value of pid = {pid}")

    print(f"Common code: PID = {os.getpid()}")

if __name__ == "__main__":
    main()

Process Creation Methods

  1. Fork-Exec Model (Unix/Linux)

    • fork(): Creates a copy of the parent process
    • exec(): Replaces the process's memory space with a new program
  2. Direct Creation (Windows)

    • CreateProcess(): Creates a new process and loads a program

Fork-Exec Example

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork();

    if (pid == 0) {
        // Child: execute 'ls' command
        execl("/bin/ls", "ls", "-l", NULL);
        // If exec succeeds, this line never executes
        perror("execl failed");
        return 1;
    } else if (pid > 0) {
        // Parent: wait for child to complete
        wait(NULL);
        printf("Child process completed\n");
    }

    return 0;
}

Process Termination

A process terminates when it finishes executing its final statement or calls exit().

Reasons for Termination

  1. Normal Exit: Process completes successfully
  2. Error Exit: Process encounters an error
  3. Fatal Error: Process encounters a fatal error (e.g., division by zero)
  4. Killed by Another Process: Terminated by parent or system

Process Termination in C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork();

    if (pid == 0) {
        // Child process
        printf("Child: Doing some work...\n");
        sleep(2);
        printf("Child: Exiting with status 42\n");
        exit(42);  // Terminate with exit status
    } else if (pid > 0) {
        // Parent process
        int status;
        wait(&status);  // Wait for child and get exit status

        if (WIFEXITED(status)) {
            printf("Parent: Child exited with status %d\n",
                   WEXITSTATUS(status));
        }
    }

    return 0;
}

Zombie and Orphan Processes

Zombie Process

A process that has terminated but whose parent hasn't called wait() yet.

Child terminates → Zombie state → Parent calls wait() → Resources released

Orphan Process

A process whose parent has terminated before it. The init process (PID 1) adopts orphan processes.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    pid_t pid = fork();

    if (pid == 0) {
        // Child process
        sleep(5);  // Child sleeps
        printf("Child: Parent PID = %d\n", getppid());
        // If parent died, PPID will be 1 (init)
    } else {
        // Parent exits immediately
        printf("Parent: Exiting\n");
        exit(0);
    }

    return 0;
}

Process Scheduling

The scheduler determines which process runs when. This is crucial for CPU utilization and system responsiveness.

Process Queues

               Job Queue (all processes)
                        |
                        v
              +---------+---------+
              |                   |
              v                   v
        Ready Queue        I/O Device Queues
              |
              v
          Scheduler
              |
              v
            CPU
              |
      +-------+-------+--------+
      |               |        |
      v               v        v
  Time slice      I/O Wait   Exit
  expired         Request
      |               |
      v               v
Ready Queue    I/O Device Queue

Scheduling Queues

  1. Job Queue: All processes in the system
  2. Ready Queue: Processes in main memory, ready to execute
  3. Device Queue: Processes waiting for I/O device

Types of Schedulers

  1. Long-Term Scheduler (Job Scheduler)

    • Selects which processes to load into ready queue
    • Controls degree of multiprogramming
    • Invoked infrequently (seconds, minutes)
  2. Short-Term Scheduler (CPU Scheduler)

    • Selects which process to execute next
    • Invoked frequently (milliseconds)
    • Must be very fast
  3. Medium-Term Scheduler

    • Swaps processes in/out of memory
    • Reduces degree of multiprogramming

Process Types

  • I/O-Bound Process: Spends more time doing I/O than computation (e.g., text editor)
  • CPU-Bound Process: Spends more time computing (e.g., scientific computation)

Exercises

Basic Exercises

  1. Conceptual Understanding

    • List the five states a process can be in and describe what each state means.
    • Explain the difference between a program and a process.
    • What information is stored in a Process Control Block (PCB)?
  2. Process States

    • Draw a state transition diagram showing how a process moves between states.
    • For each transition, give an example of what might cause it.
  3. Fork Practice

    int main() {
        fork();
        fork();
        printf("Hello\n");
        return 0;
    }
    

    How many times is "Hello" printed? Draw the process tree.

Intermediate Exercises

  1. Context Switching Analysis

    • Explain why context switching is considered overhead.
    • What factors affect the time required for a context switch?
    • How can hardware support reduce context switch time?
  2. Process Creation Write a C program that:

    • Creates a child process using fork()
    • The parent prints numbers 1-5
    • The child prints letters A-E
    • Use wait() to ensure proper ordering
  3. Process Hierarchy

    int main() {
        pid_t pid1, pid2;
        pid1 = fork();
        pid2 = fork();
        // What is the total number of processes created?
        // Draw the process tree
        return 0;
    }
    

Advanced Exercises

  1. Zombie Process Prevention Write a program that creates a child process. Demonstrate:

    • How to create a zombie process
    • How to properly handle child termination to prevent zombies
    • Use signal handlers to reap zombie processes
  2. Process Monitoring Tool Write a Python program that:

    • Lists all running processes
    • Shows PID, PPID, and process name
    • Identifies zombie and orphan processes
    • Calculates CPU usage per process
  3. Custom Shell Implement a simple shell in C that:

    • Accepts commands from the user
    • Uses fork() and exec() to execute commands
    • Supports background processes (commands ending with &)
    • Implements basic job control
  4. Performance Analysis

    • Measure the context switch time on your system
    • Create multiple processes and measure the overhead
    • Compare fork() performance with different amounts of data
    • Analyze how the number of running processes affects context switch time

Challenge Exercise

  1. Process Tree Visualizer Create a program that:
    • Reads process information from /proc filesystem
    • Builds a complete process tree
    • Displays it in a hierarchical format
    • Shows process states, PIDs, and resource usage
    • Highlights zombie and orphan processes

Summary

In this reading, we covered the fundamental concepts of operating systems and processes:

Key Takeaways

  1. Operating System Role: The OS manages hardware resources and provides services for application programs.

  2. Process Concept: A process is a program in execution, consisting of code, data, stack, heap, and execution context.

  3. Process States: Processes transition through New, Ready, Running, Waiting, and Terminated states.

  4. PCB: The Process Control Block stores all information about a process, including state, registers, memory information, and I/O status.

  5. Context Switching: The mechanism of saving and restoring process state is essential for multitasking but adds overhead.

  6. Process Creation: Processes are created using system calls like fork() in Unix/Linux, creating a parent-child relationship.

  7. Process Termination: Processes terminate normally or abnormally, and proper cleanup prevents zombie processes.

  8. Scheduling: The OS scheduler determines which process runs when, managing queues and optimizing resource utilization.

Important Concepts to Remember

  • A process is more than just code; it includes execution context and resources
  • Context switching enables multitasking but has performance costs
  • Process states reflect what the process is doing at any moment
  • The PCB is the OS's representation of a process
  • Proper process management prevents resource leaks and zombies

Looking Ahead

In the next reading, we'll explore Threads and Concurrency, examining how processes can have multiple threads of execution, the benefits and challenges of multithreading, and how to manage concurrent execution safely.

Understanding processes is fundamental to operating systems. Threads extend this concept by allowing multiple execution flows within a single process, sharing the same memory space while maintaining separate execution contexts.


Next Reading: 02-threads.md - Threads and Concurrency