Lecture 2 - Processes and Threads


Agenda

Announcements

  • Homework 1 due tomorrow night. If you have Unix or C questions, ask!
  • History Stuff from Lecture 1

    Processes and Threads

    What is a process? Our text defines it as "an abstraction of a running program."

    A process is sequential.

    Parts of a process:

  • program code (text section)
  • program counter and other registers
  • stack (local variables and function call information)
  • data (global variables)
  • A typical multiprogrammed system has many processes at any time. Try ps -aux or ps -ef to see the processes on your favorite Unix system. Only one of these can be on the processor at a time.

    States of a process:

    Process Control Block (PCB) - information needed to save and restore a process.

  • Process stare (running, waiting, ready)
  • Process identifier (PID)
  • Program counter
  • Other CPU registers
  • CPU scheduling information
  • Memory-management information
  • Accounting information
  • I/O status information
  • In many Unix systems, the PCB is divided between two structures:

  • The proc structure, which holds the process information needed at all times, even when the process is not active (swapped out).
  • The user structure, which holds other information about the process.
  • Historically, it was important to keep as much in the user structure and as little in the proc structure as possible, because of memory constraints. As memory has gotten larger, this has become less important.

    In FreeBSD, for example, most of the information is now in the proc structure. We can see it on your favorite FreeBSD system in /usr/src/sys/sys/proc.h. See struct proc to see the structure.

    The user structure is in /usr/src/sys/sys/user.h, and it is very small. It contains per-thread information. Part of this is a struct pcb, which is an architecture-dependent structure defined in /usr/src/sys/i386/include/pcb.h. Here you find the actual x86 registers that need to be saved when a process is removed from the CPU. For comparison, check out the Alpha version in /usr/src/sys/alpha/include.

    The transition is called a context switch. This is pure overhead, so it needs to be fast. Some systems do it faster than others. Hardware support helps - more on that later.

    Diagram of context switch:

    This requires at least two levels of privilege, or modes of operation:

  • User mode: execution of user processes. Low privilege. Can only access its own memory, etc.
  • Monitor mode (kernel mode, system mode): operating system execution. Can do things like switch among user processes, shut down the system, etc.
  • Hardware support is needed. Privileged instructions can be executed only while in monitor mode. We'll talk more about this as we go forward.

    The system maintains a process table and the PCBs are stored in various process scheduling queues.

    The selection of a process from the ready queue to run on the CPU is the topic for next time.

    Process Creation/Deletion

    In Unix, every process (except for the first) is created from an existing process. See ps again for examples. The processes form a tree, with the root being the init process (PID=1).

    When a new process is created, what information does it inherit from or share with its parent?

  • Does it get any resources that were allocated to the parent?
  • Does the parent wait for the child to complete, or do they execute concurrently?
  • Is the child a duplicate of the parent, or is it something completely different?
  • If it's a duplicate, how much context do they share?
  • Can the parent terminate before the child?
  • In Unix, the fork() system call duplicates a process. The child is a copy of the parent - in execution at the same point, the statement after the return from fork().

    The return value indicates if you are child or parent.

    0 is child, >0 means parent, -1 means failure (limit reached, permission denied)

    Example C program:

    pid=fork();
    if (pid) {
      parent stuff;
    }
    else {
      child stuff;
    }
    

    A more complete program that uses fork() along with three other system calls (wait(), getpid(), and getppid()) is here.

    These system calls let you, as a normal user, do things that only the system can really do. Like create a process. Your "user mode" process can get access to "kernel mode" functionality through these calls.

    The FreeBSD implementation of fork() is in /usr/src/sys/kern/kern_fork.c.

    Later, we will consider more system calls, including ones that let you do things more interesting than making a copy of yourself.

    Threads/Lightweight Processes

    Later.