I do strongly believe in abstraction being the root of computing (however, you may want to read Is abstraction the key to computing? as a motivation for a different perspective on the role of abstraction in computing). Modern hardware and software systems include a lot of features and perform so many tasks that it is impossible to understand, build and use them without recurring to abstractions. For instance, let’s take a look at the CPU: it is the central part of a general purpose computing system, and is also an extremely complex system in itself. Functionally, a CPU is an instruction-crunching device: it processes one instruction after another, following the steps of fetch, decode, execute and writeback (in von Neumann architectures). In other words, the CPU retrieves the instruction from memory, decodes it, executes it, and put the results of the operation back into memory. Further, the CPU has no clue (and actually does not care) about the higher-level semantics of the instruction it may be executing at a specific time. For example, the CPU may be executing an instruction related to a spell-checking task, and a few instructions later it may be executing an instruction related to other task, say, MP3 playing. It only follows orders, and just execute the instruction it is told to execute.
Nowadays, computing systems are expected to do more tasks on behalf of its users. Several tasks must be performed concurrently. As in the previous example, the system might be running the spell-checker and the media player simultaneously. In multiprogrammed systems we can achieve pseudoparallelism by switching (multiplexing) the CPU among all the user’s activities (true parallelism is only possible in multi-processor or multi-core systems). Remember that multiprogramming requires the CPU being allocated to each system’s task for a period of time and deallocated when some condition is met.
So far, we’ve spoken about activities and tasks, comprising a sequence of instructions. Moreover, the CPU will be multiplexed among such tasks in order to execute them in a pseudoparallel fashion. However, in order to to harness such computing power, we cannot think of long sequences of instructions, which may jump from one instruction to another at any time. We require to abstract such processing into some convenient concept or model. That model, the central unit of work of operating systems, is the process. Considering a program or code as a sequence of instructions which implement some algorithm, we can state that
a process is a running instance of a program
Passive and Active Entities
Code does nothing unless it’s executed by a CPU. But a process is a program in execution. A web browser being run by an user is a process. A compiler analyzing some input files is a process. Nevertheless, it is very important to realize that a program or raw code is not a process. A program is a passive entity, whereas a process is an active entity, for which the operating system allocates structures for controlling it and handling its resources and control information.
- Unlike passive entities, processes use resources: CPU time, memory, files and I/O devices. Such resources may be requested at creation time or during the process execution. When the process finishes its task, the operating system should reclaim or retrieve any unused resource.
- Execution of a process is sequential. Instructions are executed one after another, until the process finishes. Moreover, a process may spawn many subprocesses during its execution, by means of some system calls.
- Some processes execute system code (operating system processes) and other processes only execute user code (user processes).
- Among other responsibilities, process management involves:
- creation and termination of processes,
- suspension and resuming,
- interprocess communication,
- allocation and freeing of resources,
- setting and retrieving processes’ attributes.
In a forthcoming installment, we’ll delve into the finer details of process management.