When a context switch occurs between a user space process and a kernel routine, the current process ‘context’ needs to be saved. All the register and other runtime data is copied into the PCB and is stored for later use. The current state of the CPU (kernel or user mode) is saved in what is called a ‘state save’ and is restored later in a ‘state restore’.
Process Creation and Termination
Processes can create child processes using, for example, the fork() system call. Depending on the OS, the child process might be allocated resources directly from the OS, or be allocated a subset of its parent’s resources. This is a safety measure to prevent processes from forking out of control and crashing the system. The address space of the child could be a copy of the parent’s, or an entirely new program might be loaded into the its memory space. In UNIX, the former is the default behavior of fork(), and the latter is achieved by calling exec() after the fork. After creating a child process, the parent could simultaneously execute with the child, or wait for the child to end its execution by removing itself from the ready queue (by using the wait() system call in UNIX).
Processes are terminated using the exit() system call. It may send a status value (usually integer) to its parent process and has its resources deallocated by the OS.
In some situations (such as the child exceeding resource usage, or its services no longer being required), the parent might need to terminate the child process. Some systems also require that parents wanting to terminate themselves need to kill their children first. Systems such as VMS automatically perform cascading termination on orphaned processes. UNIX doesn’t require this, and assigns init as the new parent process of any orphaned processes.
Independent processes are those which cannot affect or be affected by any other processes in execution. Cooperating processes are those who share data and communicate with other processes in execution. Cooperating processes are important because it allows for:
- Information sharing (concurrent access to shared information)
- Computational speedup (breaking one process into many cooperating processes that run in parallel)
- Modularity (dividing system functionality into separate threads)
- Convenience (allows users to multitask)
There are two fundamental approaches to Interprocess Communication (IPC):
- Shared memory (a shared region of memory where both processes can read and write to)
- Message passing (messages exchanged between processes using system calls)
Message Passing is easier to implement, there are no conflicts that need to be avoided and it works great for small amounts of data. But the downside is that it uses system calls (which means the messages go through the kernel) and is hence slow.
Shared Memory requires system calls only to establish the shared regions of memory. Usually this is allocated from the memory space of the process that wants to create the region. After the region is created, the process that created it allows other specified processes to access that region (which overrides the normal OS memory protection rules). The kernel no longer intervenes in the management of that region of memory, and the processes can communicate at memory speed. They are also responsible for avoiding read/write conflicts. The shared memory process is described as follows:
A producer produces information → Information is stored in bounded or unbounded buffer → A consumer waits for the information to be produced before consuming it