In this section, I would like to give you a simple concept about process, inter-process communication and its system calls. Also, I have tried to point out some of its differences with a program.
To tell something about a process, we should know what a virtual computer is. Using hardware components and resources of a physical computer, we can implement a computer in software known as virtual computer and its basic components are also the same as that of a physical computer. I/O, disk, memory and processor and each of its resources will be a multiplexed and transformed version of physical resources of a physical computer. Thus an operating system can itself create any number of virtual computers and when we use one of those virtual computers to execute a program, that particular program is known as a process. For each process, a virtual computer is created by the operating system and thus the running process is given an illusion that it is using its own physical memory. Thus a new execution environment is created where a process or more than one process runs at the same time. Best example for a multi-process environment is compiling a program in the background while giving next input or editing in the foreground.
A program and a process - How they differ?
A program is a static object while process is a dynamic activity. A program exists in a file that contains a sequence of instructions or algorithm to run it, while a process is a program in execution, that contains a sequence of instruction executions. A program is something that is stored and hence it always exist in a single place in space. But process has only a limited span or time and when its set of instructions are completely executed, they exit.
Let us see a simple C program that calculates the sum of 1000 integers.
A single line of code is needed to represent 1000 iterations in a program. But the process has to execute 1000 times, once it enters the loop, to give the final result which make it different from a program with lines of code.
How new processes are created
A process can itself create new processes using system calls. New processes can be created with or without passing arguments. A brief description of these two processes is given below.
Without arguments
Operating system allows a process to create new processes if needed. If so, newly created process has to terminate first and then only the main process can exit. Only 3 system calls are needed for a sequence of such instructions - create, exit and wait. It is very easy to use, but does not allow to pass any return value to the called process.
int WithoutArgCreateProcess( char *pgmName ); - As soon as this code is executed, a new process is created with name pgmName. The process identifier of the new process is returned.
void WithoutArgWait( int pro_id ); - This is a waiting call and hence the calling process will wait until the process specified by the process identifier pro_id terminates. For, example, while executing subroutine or function without any return value, the subfunctions has to be completed and resources released first. Then only main process can continue or exit.
int WithoutArgExit( void ); - The process that makes the system call terminates.
When a new program is initiated, operating system creates the first process and that process creates newer ones according to the sequence of instruction executions. i.e. WithoutArgCreateProcess system call is used to create all process and each process makes a WithoutArgExit system call to exit the process when it is finished. Holding resources are also freed along with exit system call. Each process is assigned by a unique integer number key known as process identifier to identify each process. A process can wait for other process to exit as long as it knows the process identifier of the one, that it wants to wait for.
With arguments
Here, system calls allow us to send arguments to processes we create and argument may be of any number which varies from one to another integer value. In addition to passing an information to a process, it returns a value to us when it exits. Thus the exiting process always send a return code of integer type to the process that waits for it. Here also system calls are create, wait and exit, but not a void return value.
int WithArgCreateProcess( char *pgmName, int argCount, char *argVectArray[ ]); - As soon as this code is executed, a new process is created with name pgmName. Return value is the process identifier of the new process. The arguments are in the argument vector VectArray, which are an array of strings which act as array of pointers to characters. The argument count is given by the integer value argCount, i. e, the total number of pointers to strings in argVectArray. If the process is not created, it returns -1 as return code. If the newly created process pgmName could not be read, it returns value -2.
void WithArgWait( int pro_id ); - This is a waiting call and hence the calling process will wait until the process specified by the process identifier pro_id terminates. The return value is the return code given by the process when it is exited. For, example, while executing subroutine or function with any return value, the subfunctions has to be completed and return some integer value to the calling process. Then only main process can proceed or exit.
void WithoutArgExit( int retCode ); - As soon as this system call is executed, the corresponding process exits. The return code will be returned to the parent process.
Process hierarchy
When a process creates another one, the creator is called parent process and the newly created process is called child process. Parent process has full control over its child and it can terminate, send messages, look into the memory or temporarily stop the child whenever it feel so. Their relationship can be illustrated with the help of a tree structure known as process hierarchy.
A child can in turn create its own children. Accounting information of children are stored in the parent by the operating system. Resource allocation is done by the parent process itself and each parent further do the same process for its children. Each parent has to wait till its child process completes, which is best shown in the process hierarchy diagram. But, if parent process terminates automatically due to some abrupt, then its children also terminates. But in some operating systems like UNIX, such orphan children are reparented to somewhere else in the process hierarchy.
Interprocess communication
Sometimes, processes want to communicate each another, while they are running. This process is known as interprocess communication or simply IPC. This process is done with the help of a message queue by a simple process of buffering. Each process can create its own message queue and any other process can send or receive messages from it. Thus, a process can send a message at any time which will be added to the message queue of the receiving process and will be received by it when its turn comes. Thus a message queue contains already send messages that have not been received yet. Each message will have a unique address and it contains 8 words. Message is normally small in size, since it is difficult to send large quantities of data through buffering. A process can send any number of messages to different message queues and can receive from several ones.
System calls of IPC
System calls of interprocess communication include system calls to create a new message queue, send and receive and destroy a message queue. They are briefly described below.
int CreateNewMsgQueue( void ); - Creates a new message queue and its key identifier is returned to the caller.
int SendMsg( int msg_queue_id, int *msg_buff); - The message in the message buffer msg_buff is send to the message queue with identifier msg_queue_id. If the message is send successfully, it returns '0' as return value. if message queue identifier, msg_queue_id is invalid, it returns -1 and if msg_buff is an invalid address, it returns -2. Message buffer is an array of 8 integers.
void ReceiveMsg( int msg_queue_id, int *msg_buffer); - The first received message in the message queue with identifier msg_queue_id is copied into msg_buffer. Here also, it contains an array of 8 integers. It returns '0' if a message is received successfully. If msg_queue_id is an invalid message queue identifier, it returns -1 and and returns -2 if msg_buffer is an invalid address.
int DestroyMsgQueue( int msg_queue_id); - The message queue with identifier msg_queue_id will be destroyed and all its unreceived messages are also discarded. Thus the identifier msg_queue_id becomes invalid for further sending and receiving of messages. If this process is successful, return value is 0, otherwise -1.
Message passing is the simplest form of communication between the processes and of course, it is very important for the completion of processes under the guidance of the operating system.