13.4.2. Message Passing

One way in which processes with private virtual address spaces can communicate is through message passing: by sending and receiving messages to each other. Message passing allows programs to exchange arbitrary data rather than just a small set of predefined messages like those supported by signals. And operating systems typically implement a few different types of message passing abstractions that processes can use to communicate.

The message passing interprocess communication model consists of three parts:

  1. processes allocate some type of message channel from the OS. Example message channel types include pipes for one-way communication, and sockets for two-way communication. There may be additional connection set-up steps that processes need to take to configure the message channel.

  2. processes use the message channel to send and receive messages to each other.

  3. processes close their end of the message channel when they are done using it.

A pipe is a one-way communication channel for two process running on the same machine. One-way means that one end of the pipe is for sending messages (or writing to) only, and the other end of the pipe is for receiving messages (or for reading from) only. Pipes are commonly used in shell commands to send the output from one process to the input of another process.

For example, consider the following command entered at a bash shell prompt that creates a pipe between two processes (the cat process outputs the contents of file foo.c and "pipe" (|) redirects that output to the input of the grep command that searches for the string "factorial" in its input):

$ cat foo.c | grep factorial

To execute this command, the bash shell process calls the pipe system call to request the OS to create a pipe communication. The pipe will be used by the shell’s two child processes (cat and grep). The shell program sets up the cat process’s stdout to write to the write-end of the pipe and the grep process’s stdin to read from the read-end of the pipe, so that when the child processes are created and run, the cat process’s output will be sent as input to the grep process:

example of a pipe sending cat’s output to grep’s input
Figure 1. Pipes are unidirectional communication channels for processes on the same system. In this example, the cat process sends the grep process information by writing to the write-end of the pipe. The grep process receives this information by reading from the read-end of the pipe.

While pipes transmit data from one process to another in only one direction, other message passing abstractions allow processes to communicate in both directions. A socket is a two-way communication channel, which means that each end of a socket can be used for both sending and receiving messages. Sockets can be used by communicating processes running on the same computer or running on different computers connected by a network. The computers could be connected by a local area network (LAN), which connects computers in a small area, such as a network in a university computer science department. The communicating processes could also be on different LANs, connected to the Internet. As long as there exists some path through network connections between the two machines, the processes can use sockets to communicate.

sockets enable two processes on different machines to communicate across a network.
Figure 2. Sockets are bidirectional communication channels that can be used by communicating processes on different machines connected by a network.

Because each individual computer is its own system (hardware and OS), and because the OS on one system does know about or manage resources on the other system, message passing is the only way in which processes on different computers can communicate. To support this type of communication, operating systems need to implement a common message passing protocol for sending and receiving messages over a network. TCP/IP is one example of a messaging protocol that can be used to send messages over the Internet. When a process wants to send a message to another, it makes a send system call, passing the OS a socket on which it wants to transmit, the message buffer, and possibly additional information about the message or its intended recipient. The OS takes care of packing up the message in the message buffer, and sending it out over the network to the other machine. When an OS receives a message from the network, it unpacks the message and delivers it to the process on its system that has requested to receive the message. This process may be in a blocked state waiting for the message to arrive. In this case, receipt of the message make the process ready to run again.

There are many system software abstractions built on top of message passing that hide the message passing details from the programmer. However, any communication between processes on different computers must use message passing at the lowest-levels (communicating through shared memory or signals is not an option for processes running on different systems). In the Parallel Systems Chapter, we discuss message passing and the abstractions built atop it in more detail.