Related Content: CS604 - VU Lectures, Handouts, PPT Slides, Assignments, Quizzes, Papers & Books of Operating Systems
The wait system call suspends the calling process until one of the immediate children
terminate, or until a child that is being traced stops because it has hit an event of interest.
The wait will return prematurely if a signal is received. If all child processes stopped or
terminated prior to the call on wait, return is immediate. If the call is successful, the
process ID of a child is returned. If the parent terminates however all its children have
assigned as their new parent, the init process. Thus the children still have a parent to
collect their status and execution statistics. The synopsis of the wait system call is as
follows:
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *stat_loc);
A zombie process is a process that has terminated but whose exit status has not yet been received by its parent process or by init. Sample code showing the use of fork() and wait() system calls is given in Figure 7.1 below.
Typically, the execlp() system call is used after a fork() system call by one of the
two processes to replace the process’ memory space with a new program. The new
process image is constructed from an ordinary, executable file. This file is either an
executable object file, or a file of data for an interpreter. There can be no return from a
successful exec because the calling process image is overlaid by the new process image.
In this manner, the two processes are able to communicate and then go their separate
ways. The synopsis of the execlp() system call is given below:
#include <unistd.h>
int execlp (const char *file, const,char *arg0, ...,
const char *argn,(char *)0);
Sample code showing the use of fork() and execlp() system calls is given in Figure 7.2 below.
The semantics of fork(), followed by an execlp() system call are shown In Figure 7.3 below.
The concurrent processes executing in the operating system may be either independent
processes or cooperating processes. A process is independent if it cannot affect or be
affected by any other process executing in the system. Clearly any process that shares
data with other processes is a cooperating process. The advantages of cooperating
processes are:
To illustrate the concept of communicating processes, let us consider the producer consumer problem. A producer process produces information that is consumed by a consumer process. For example, a compiler may produce assembly code that is consumed by an assembler. To allow a producer and consumer to run concurrently, we must have available a buffer of items that can be filled by a producer and emptied by a consumer. The producer and consumer must be synchronized so that the consumer does not try to consume an item that has not yet been produced. The bounded buffer problem assumes a fixed buffer size, and the consumer must wait if the buffer is empty and the producer must wait if the buffer is full, whereas the unbounded buffer places no practical limit on the size of the buffer. Figure 7.4 shows the problem in a diagram. This buffer may be provided by interprocess communication (discussed in the next section) or with the use of shared memory.
Figure 7.5 shows the shared buffer and other variables used by the producer and consumer processes.
The shared buffer is implemented as a circular array with two logical pointers: in an out.
The ‘in’ variable points to the next free position in the buffer; ‘out’ points to the first full
position in the buffer. The buffer is empty when in==out, the buffer is full when
((in+1)%BUFFER_SIZE)==out. The code structures for the producer and consumer
processes are shown in Figure 7.6.