Inter-Process Communication

Buddhika Chathuranga
RuntimeError
Published in
8 min readApr 21, 2020

--

We know that many processes are running in an operating system concurrently. Processes running concurrently means there may be two or more processes run at the same time. But the actual concurrent concept is a lot more than that and read this article to learn about the concurrency of a computer system. Now when processes run concurrently, we can identify two types of processes.

  • Independent processes 🚶
  • Co-operating processes 👭

Independent process means that anything happens in that process will not affect other processes that are executing and anything happens in other processes will not affect this process. Co-operative processes are processes which depend on other processes running in a computer system. Simply, co-operative processes are processes that are sharing data. That means those processes need to communicate with each other to know their states. When processes communicate with each other, we call that Inter-process communication(IPC). It’s much simpler than you think😛

Now we know that inter-process communication is two or more processes sharing data. In a modern computer system, there are two models of doing this.

  • Shared Memory
  • Message Passing

In the shared memory model, processes using a shared portion of memory to communicate data. One process can write to that memory and another process can read from that memory.

In the message-passing model, the process is not using a shared memory portion. Process directly sends data to other processes, which they need to communicate with.

Shared memory model

Interprocess communication — Shared memory model

Now we know that the shared memory model has a shared portion of memory to communicate data between processes. Let us imagine there are two processes called P1 and P2 and those processes need to communicate. Let’s say P1 needs to send some data to P2. The following steps describe how this will happen.

Step 1: First P1 establish a shared memory region in P1’s address space.

Step 2: Now P2 should attach that shared memory region to its address space. Then P1 writes data that needs to share with P2 in the shared memory region.

Step 3: P2 reads data from the shared memory region.

Now there are a few important points that we should keep in mind about the shared memory model. As you see, always shared memory region initiate inside an address space of one process. Literally, inside the address space of the process which needs to initiate the communication. And then other processes need to attach that memory space into its memory and we know that the operating system does not allow to access the address space of a process by another process. So if a shared memory system needs to be executed, then the operating system has to remove that restriction of one process can’t access another processes address space.

We can see this model as a producer-consumer model. One process will produce the data and another process will consume the data. We call buffer to this shared memory region. When processes writing and reading using this buffer, those processes need to be synchronized well, so that the consumer process will not try to read data that the producer has not produced yet. The race condition may arise if both the processes i.e. producer process and consumer process try to access the shared data concurrently.

There are two types of buffers.

1.Bound Buffer

Bound buffer has a limit of size. With this type of buffer, the consumer has to wait if the buffer is empty and the producer has to wait if the buffer is full.

2.Un-bound buffer

There is no limit of size in this type of buffer. In this case, the consumer has to wait if the buffer is empty. But producers can always produce data since there is no limitation of the size of the buffer.

There are both pros and cons in the shared memory model.

Pros and Cons of shared memory IPC

Message Passing Model

Inter-Process Communication — Message Passing Model

The message-passing model provides a mechanism to allow processes to communicate and to synchronize their actions without sharing memory and this model is particularly useful in distributed systems, where the communication process resides on two computers connected by a network. Now let’s see how the message passing model works inside.

In message-passing models, there are two main operations.

  1. Send — sending a message to a process
  2. Receive — receive a message from a process

According to the size of the message, there are two types of messages in a message-passing system.

  1. Fixed-size messages
  2. Variable size messages

Fix Size Message — The message has a fixed size. System-level implementation of this type is straight forward. But make the task of programming more difficult. Imagine a process that has to send a message to another process, which is bigger than the message size limit. Then the producer process has to break the message into parts and send using mechanisms like serializing. Some systems, if the data that has to pass with the message is too big, send the pointer of the data. This depends on the system design.

Variable Size Message — There is no limit to the message size. System-level implementation is a bit difficult. The system has to allow any size of the message. But the programming task becomes much easier. A producer has not to worry about the size of the message.

When two processes communicating using the message-passing model, there should be a logical link between these two processes. There are various ways of creating this link logically and physically. Here we are going to talk about only how logically implement this link between processes.

Logical link between two processes

Processes can execute send() and receive() operations via this logical link. As I mentioned before there are various ways to implement this link and send(), receive() operations.

  • Direct or Indirect Communication
  • Synchronous or Asynchronous Communication
  • Automatic or Explicit Buffering

Also, there are few issues related to these implementations such as

  • Naming issues
  • Synchronization issues
  • Buffering Issues

Let’s talk about this in deep.

Direct and Indirect Communication

Direct Communication

Indirect communication model, each process must explicitly specify the sender or the receiver. See the below example.

send(P, message)
receive(Q, message)

This process sends a message to process P and receives a message from process Q. It has explicitly specified the sender and the receiver. The logical link created between these types has few properties. The link is associated with exactly two processes and there is only one link between two processes. Processes must know the producer process and consumer process. We call this symmetry in addressing. Because both the sender and the receiver have explicitly named.

There is another variety of this direct message passing.

send(P, message)
receive(pid, message)

In this case, specify only the receiver explicitly. This process sends a message to process P and receives a message from any process. We call this asymmetric in addressing.

There are some disadvantages to this direct communication model. This limits the modularity of a program. If one process reference changed, all other processes which depend on that process need to be changed.

In-direct communication

Indirect communication model using mailbox or ports to passing messages. The mailbox is a sort of abstraction to a memory location that is used by processes to save messages and retrieve messages. Each mailbox has a unique identification and two processes can share messages if both have a shared mailbox. The mailbox may own either by the process or the operating system. It will depend on the system implementation. Refer to this example.

Send(A, message)
Receive(A, message)

Here is the mailbox. The process can send messages to mailbox A and processes can receive a message from mailbox A. When using a mailbox more than two processes can participate in a communication channel. Because of that, some issues can occur. Refer to the below situation.

Process A sends a message to the mailbox and Process B and Process C can receive the message. Now the problem is who is going to receive the message among Process B and Process C. There are a variety of workarounds to prevent this issue.

  • Allow links to be associate with two processes at most so that only two processes will communicate using the mailbox. So there will be only one receiver process at once.
  • Allow at most one process to execute receive() operation.
  • Allow the system to select, which process will receive the message. The system can use priority algorithms to select the process which will receive the message.

Synchronous or Asynchronous Communication

We know that message passing between processes is happen using send() and receive() primitives. There are different design options for implementing each primitive. According to this design, message passing may be either blocking or non-blocking. We can call this synchronous or asynchronous. According to this blocking or non-blocking design, we can divide message passing into 4 categories.

  1. Blocking Send — The sending process is blocked until the receiving process gets the message from the mailbox.
  2. Non-blocking send — The sending process sends the message and continues its operations. The sender doesn’t worry whether the receiver gets the message from the mailbox or not.
  3. Blocking Receive — Receiving process blocked, until a message is available.
  4. Non-blocking Receive — Receiving process receive either a message or null. Receive the process not to wait until the message arrives.If the message available then get the message. If the message is not available, then receive the null and continues.

When a process is blocking we call that synchronous, and when a process is not blocking we call asynchronous.

Buffering

Whether the communication is direct or indirect, messages reside in a temporary message queue. We call that buffer. Such queues can be implemented in three ways.

  1. Zero Capacity Buffer — In this queue maximum capacity is zero. Hence messages can’t wait in the queue until a process receives the message. So in this case, if the process wants to make sure that the receiver gets the message, the sender has to wait until the receiver gets the message.
  2. Bound Capacity Buffer — This queue has a limited capacity of n. So n messages can wait in the queue until the receiving process retrieve the message. So the sender has not to wait until the receiver gets the message. But since the queue has limited capacity, if the queue is full then the sender has to wait or block until space available for the message in the queue.
  3. Unbounded Capacity Buffer — There is no limit in the queue. So an infinite number of the message can wait in the queue. So the sender never has to wait.

Recap

  • Two types of processes in a computer system. Independent and co-operative.
  • The process needs to communicate with each other. We call that inter-process communication and processes using two operations as send() and receive() to communicate.
  • There are two main ways to communicate between processes. Those are shared memory and message passing.
  • Shared memory using a shared portion of memory and message passing doing via direct or indirect links.
  • In message passing, there are two varieties. Using direct links or Using Mail Box.

--

--