As you know, abstraction is a fundamental design tool in many areas of computer science. In the realm of operating systems, we have already noted that the fundamental abstraction is the notion of a process.
Recall that a process is a program in execution. At any given time, the status of a process includes:
The code that it is executing (its text).
Its data
The values of its static variables.
The contents of its stack - which contains its local variables and procedure call/return history.
The contents of the various CPU registers - particularly the program counter, which indicates what instruction the process is to execute next.
Its state - is it currently able to continue execution, or must further execution wait until some event occurs (e.g. the completion of an IO operation it has requested)
The chief task of an operating system is to manage a set of processes.
In the simplest case (e.g. one-user microcomputers), there is only one process to manage.
The interesting case arises when there are many processes competing for system resources.
On a one CPU system, there is, at any given time, at most only one current process - namely the one whose code the hardware PC register is actually pointing to. Given that there may be many processes that wish to use the CPU, one task of the operating system kernel is scheduling - i.e. determining which process should be current at any given time.
Of course, on a system with multiple CPU's there can be more than one current process - but at most one per CPU.
Though we use the term process, other terms have been and are still used for the same concept, including job and task (though each term is also sometimes used to mean something different.)
To manage the various processes, the operating system maintains a set of data structures called process control blocks (PCB's) - one per process.
Each PCB contains information about its process, including:
The state of the process.
The values of the CPU registers (relevant only when the process is not running; when it is running, these values change constantly) Note: The set of values may include both values visible to the programmer and hidden registers such as memory base and limit registers.
Memory management information
Scheduling, accounting, and resource allocation information.
One major use of the PCB's is in conjunction with a context switch operation.
A context switch occurs whenever the a new process is given use of the CPU in place of the one that is currently running.
During a context switch, the first thing that must happen is that the register values associated with the currently running process must be stored into its PCB, to be saved until the process next gets a chance to run.
Then, the stored register values found in the PCB of the new process are copied into the CPU registers.
Example: Suppose we have a CPU with 5 registers: PC, SP, AC, memory base, and memory limit. Suppose further that we have the following scenario: process 17 is currently running, and we wish to do a context switch to process 12. The following occurs
BEFORE CPU Registers PCB 17 PCB 12 PC 1050 (Irrelevant) 6124 SP 2F48 6984 AC 0000 0100 Base 1000 5000 Limit 3000 8000 AFTER CPU Registers PCB 17 PCB 12 PC 6124 1050 6124 SP 6984 2F48 6984 AC 0100 0000 0100 Base 5000 1000 5000 Limit 8000 3000 8000Note: As process 12 runs, the values in the CPU registers will change. Its PCB will not be updated to reflect these changes until the next context switch.
One of the most important sets of services an operating system provides is those related to the management of processes - including:
Process creation. Most systems allow a process that is running to create a new process.
The creator process is called the parent and the new process is called a child. (By repeated use of the create process service, a parent could create multiple children, of course.)
Various aspects of the relationship between a parent and child are handled differently by different systems:
Memory image:
Unix: When a child process is created by the fork() system call, it shares its parent's text and inherits a copy of its parents data. The child can later acquire its own, separate text by using the execve system call.
VMS: The CREPRC system service must specify an executable image file which is loaded to become the text of the child process. The parent and child share neither text nor data.
Resources: Most systems impose some upper limits on how large a quantity of various system resources a process can claim (e.g. memory, open files etc.) On some systems, the resources used by a child are counted against its parents quota; on others each child has its own quota.
Possibility of the child living on after the parent terminates. On some systems (e.g. VMS) termination of a parent process automatically causes its children to terminate as well.
Process termination
A process may terminate itself by invoking a suitable system service.
On many systems, a parent process may also terminate one of its children through a system service call.
Allocation of resources
CPU time
Memory
IO Devices
Facilities for cooperation between processes
Some systems allow processes to share physical memory, so that data written to a given location by one process can be read by another. (Of course, this is never possible if the processes reside on distinct systems in a network). The operating system must, in this case, provide services for declaring a given region of memory to be shared and for attaching to a shared region that was created by another process.
Most systems allow processes to communicate with one another by means of messages. The operating system must provide facilities for sending and receiving messages. (These may be transmitted within a single computer, or over a network.)
Most systems provide some services for synchronization of processes, so that one process can wait until another process has reached a certain point in its execution. This is especially important when shared memory is used - a process that intends to access data that another has written has to wait until the other process has done so.
We have said that an operating system manages a set of processes. In recent years, the notion of process has been broadened to include two kinds of processes - traditional, or heavy weight processes, and light weight processes - also known as threads.
The motivation for this developement is a desire to balance considerations of efficiency with considerations of software modularity.
The use of multiple processes (of any sort) entails periodic context switches, in which the CPU is passed from one process to another. Unfortunately, a context switch operation can be quite time-consuming, especially if a significant number of memory-management related values must be saved and restored. Thus, one consideration in designing an efficient system is avoiding excess context switching.
On the other hand, a current trend in the design of complex software systems is to organize these systems as a set of cooperating processes, rather than as a single monolithic process.
For example, as noted in the text a "producer and consumer" sort of problem is often most cleanly structured as a pair of processes, perhaps with a third buffer process mediating between them.
A server system (such as a file server) may be structured as one process per client served.
The structuring of tasks as a collection of concurrent processes leads, of course, to increased frequency of context switching - which conflicts with our previously-stated goal of minimizing context switches for efficiency reasons.
Further, if a task is structured as a collection of cooperating processes, then message-passing overhead is involved when the processes need to communicate with each other. (This is not an issue when a task is structured as a single process, or when a collection of processes operate independently of one another.)
One way to resolve the tension between modularity and efficiency is to allow a single process to be structured as a set of individual threads.
All the threads share the same memory context (code and data). There is no memory protection between threads in the same process - any thread may alter any data item.
Each thread has its own register context (including PC and SP), and its own stack. (All the stacks for the various threads are located in the same data space; but since each has its own SP each uses a different "chunk" of this space for its stack.)
Threads have two major advantages:
A context switch between threads it the same process is much faster than a context switch between processes, since only register context needs to be saved and restored - not memory management context. Thus one can have the modularity advantages of separate processes with less overhead.
Since all the threads share the same data, information sharing between the threads does not require the overhead of message passing.
Threads can be implemented in two different ways:
By the use of library routines that run in user mode, independent of the operating system. (I.e. the operating system manages a single process; the process manages its own threads.)
By adding a threads facility to the operating system. We now have distinct system services for:
Creating a new process (initially consisting of a single thread).
Creating a new thread within an existing process.
The former approach is simpler, and minimizes the overhead involved in a context switch between threads (since no system call is involved). The latter, however, allows one thread in a process to block itself on an IO operation while allowing the other threads to continue executing. For this reason, some systems make both approaches available.
On a system that provides threads, processes are usually not allowed to share memory, but threads within a given process always share memory. Processes communicate among themselves by message passing; threads normally communicate through shared memory (though they may also use message passing among themselves if desired.)
A note on terminology:
The terms thread and light weight process (LWP) are often used interchangeably.
The term task or heavyweight process is sometimes used to refer to the set of threads sharing a common body of memory.
We will use the terms process and thread in subsequent lectures.
$Id: processes_threads.html,v 1.1 1998/02/01 22:44:03 senning Exp $
These notes were written by Prof. R. Bjork of Gordon College. In January 1998 they were converted to HTML and lightly editited by J. Senning of Gordon College.