Inter-Process Communication:Creating A New Process and The fork() System Call.
Module 7: Inter-Process Communication
Processes execute to accomplish specified computations. An interesting and innovative way to use a computer system is to spread a given computation over several processes. The need for such communicating processes arises in parallel and distributed processing contexts. Often it is possible to partition a computational task into segments which can be distributed amongst several processes. Clearly, these processes would then form a set of communicating processes which cooperate in advancing a solution. In a highly distributed, multi-processor system, these processes may even be resident on different machines. In such a case the communication is supported over a network. A comprehensive coverage of distributed systems is beyond the scope of this book. There are texts like Tanenbaum and Steen [8] which are exclusively devoted to this topic. All the same, we shall study some of the basics to be able to do the following:
- How to spawn (or create) a new process.
- How to assign a task for execution to this newly spawned process.
- A few mechanisms to enable communication amongst processes.
- Synchronization amongst these processes.
In most cases an IPC package is used to establish inter-process communication. Depending upon the nature of the chosen IPC, the package sets up a data structure in kernel space. These data structures are often persistent. So once the purpose of IPC has been fulfilled, this set-up needs to be deleted (a clean up operation). The usage pattern of the IPC package in a system (like system V Unix) can be seen by using explicit commands like ipcs. A user can also remove any unused kernel resources by using a command like ipcrm.
For our discussions here, we shall assume Unix like environment. Hopefully, the discussion here offers enough information to partially satisfy and raise the level of curiosity about the distributed computing area.
Creating A New Process: The fork() System Call
One way to bring in a new process into an existing execution environment is to execute fork() system call. Just to recap how system calls are handled, the reader may refer to Figure 7.1. An application raises a system call using a library of call functions. A system call in turn invokes its service (from the kernel) which may result in memory allocation,
device communication or a process creation. The system call fork() spawns a new process which, in fact, is a copy of the parent process from where it was invoked!! The newly spawned process inherits its parent's execution environment. In Table 7.1 we list some of the attributes which the child process inherits from its parent.
Note that a child process is a process in its own right. It competes with the parent process to get processor time for execution. In fact, this can be easily demonstrated (as we shall later see). The questions one may raise are:
- Can one identify when the processor is executing the parent and when it is executing the child process?
- What is the nature of communication between the child and parent processes?
The answer to the first question is yes. It is possible to identify when the parent or child is in execution. The return value of fork() system call is used to determine this. Using the return value, one can segment out the codes for execution in parent and child. We will show that in an example later.
The most important communication from parent to child is the execution environment which includes data and code segments. Also, when the child process terminates, the parent process receives a signal. In fact, a signal of the termination of a child process, is one feature very often exploited by programmers. For instance, one may choose to keep parent process in wait mode till all of its own child processes have terminated. Signaling is a very powerful inter-process communication mechanism (using signals) which we shall learn in Section 7.3.5. The following program demonstrates how a child process may be spawned.
The program: Demonstration of the use of fork() system call
The reader should carefully examine the structure of the code above. In particular, note how the return value of system call fork() is utilized. On perusing the code we note that, the code is written to execute in different parts of the program code for the child and the parent. The program makes use of true return value of fork() to print “In parent", i.e. if the parent process is presently executing. The dummy loop not only slows down the execution but also ensures that we obtain interleaved outputs with a manageable number of lines on the viewing screen.
Response of this program:
Let us study the response. From the response, we can determine when the parent process was executing and when the child process was executing. The final line shows the result of the execution of line following wait command in parent. It executes after the child has fallen through its code. Just as we used a wait command in the parent, we could have also used an exit command explicitly in the child to exit its execution at any stage. The command pair wait and exit are utilized to have inter-process communication. In particular, these are used to synchronize activities in processes. This program demonstrated how a process may be spawned. However, what one would wish to do is to spawn a process and have it execute a planned task. Towards this objective, we shall next populate the child code segment with a code for a specified task.
Comments
Post a Comment