Processes frequently need to communicate with other processes. For example, in a shell pipeline, the output of the first process must be passed to the second process, and so on down the line. Thus, there is a need for communication between processes, preferably in a well-structured way not using interrupts. Because, interrupts decrease system performance.
That communication between processes in the control of the OS is called as Interprocess Communication or simply IPC
In some operating systems, processes that are working together often share some common storage area that each can read and write. To see how IPC works in practice, let us consider a simple but common example, a print spooler.
When a process wants to print a file, it enters the file name in a special spooler directory. Another process, the printer daemon, periodically checks to see if there are any files to be printed, and if there are, it sends them to printer and removes their names from the directory.
Assume that our spooler directory has a large number of slots, numbered 0, 1, 2, …, each one capable of holding a file name. Also suppose we have two shared variables, out, which points to the next file to be printed, and in, which points to the next free slot in the directory. These two variables might be kept on a two-word file available to all processes. Think of a certain instant, slots 0 to 3 are empty (the files have already been printed) and slots 4 to 6
are dull (with the file names to be printed).
More or less frequently, processes A and B decide they want to queue a file for printing as illustrated below.
The following might happen about the printing requests of two processes. Process A reads in and stores the value, 7, in a local variable next_free_slot. Just then a clock interrupt occurs and the processor decides that process A has run long enough, so it switches to process B. Process B also reads in, and also gets a 7, so it stores the name of its file in slot 7 and updates in to be an 8. Then it goes off and does other things.
Eventually, process A runs again, starting from the place it left off. It looks at next_free_slot, in its local variable finds a 7 there, and writes its file name in slot 7, erasing the name that process B just put there. Then, it computes next_free_slot + 1, which is 8, and sets in to 8.
The spooler directory is now internally consistent, so the printer daemon will not notice anything wrong, but process B will never get an output. Situations like this, where two or more processes are reading or writing some shared data and the final result depends on who runs precisely when, are called race conditions
The key for preventing trouble here and in many other situations involving shared memory, shared files, and shared everything else, is to find some way to prohibit more than one process from reading and writing the shared data at the same time. Put in other words, what we need is mutual exclusion (some way of making sure that if one process is using a shared variable or file, the other process will be excluded from doing the same thing.
The difficulty above occurred because process B started using one of the shared variables before process A was finished with it.