Chapter 14 IPC without shared memory

Exercises

14-1 Contrast the UNIX pipe facility for same-machine, cross-address-space IPC with message passing.

The UNIX pipe is designed to make IPC look like file and device I/O. An arbitrary number of bytes may be sent to or received from a pipe at any time. There is no concept of "the end of this communication". Any structuring must be done by the application.

Message systems pass blocks of data from a source to (a) destination specified in the message header. The message transport service does not interpret the message body so, again, the application must impose any internal structure on the message contents. A message is defined as a discrete unit, unlike the stream model of a pipe.

Both pipes and messages allow sender and receiver to synchronise. WAIT for a message or read more bytes from the pipe - if it’s empty you are blocked.

You may be blocked on sending to a "full" pipe (some system determined size). The system may take steps to prevent you from sending too many messages, see Chapter 24.

14-2 Suggest ways in which memory management hardware could be used for passing large messages between processes in separate address spaces. Consider both the case when the message is available to both sender and receiver after the message is sent and the case when the send involves only a transfer from one address space to another. Which semantics do you think should be the default and why?

The pages of the message (which may have been acquired for this purpose before the message was created) are mapped into the receiver’s address space to make the message available to it. The convention may be that the message is first mapped into a system area so that the processes (page tables) are not constrained to be in main memory at the same time.

Ideally, one should be given a choice of share or transfer semantics. One scenario is that sender and receiver may wish to co-operate over processing the message data which has become shared. Another is that the sender should not be allowed to change the message data once it has been sent. Systems differ in their assumptions. See Chapter 22 for examples.

14-3 Suggest two ways in which the handling of message passing between processes may be unified with process-device interactions.

1) Each device becomes equivalent to a process. Device handlers do output by message passing to the device; the system interprets the process name as a device and carries out the I/O. An interrupt causes a message to be sent to the (single) device handler process. A processes model of the world is that all interaction is achieved by message passing.

2) The implementation of message passing may be unified with the event handling mechanisms of the system. Arrival of a message is considered as a type of event.

14-4 What problems do you think would arise if synchronous message passing was used to implement interactions between client processes and heavily used servers. How would you solve these problems?

Clients would be delayed for long periods waiting for service. It is out of the question that servers should wait for clients to synchronise in order to return the results of the service invocation. We must have buffering. As this is not provided by the system it must be implemented at the process level.

14-5 How can language-level type checking be included in a message passing system?

It is straightforward to define a message structure, for example as a record with typed fields. What is required, in addition, is a mechanism for type checking between sender and receiver.

One approach is to use output ports and input ports. A port can be declared as taking only messages of a specified type. This type checking is internal to the process. It remains to make a binding between an output port and an input port at which stage the types of the ports are checked. This could be done statically at system configuration time (as in Conic) or dynamically at run-time by means of a system naming and binding service. Section 15.9 gives an example in the context of an RPC system, the ANSA interface trader.

If the system is not written in a single language the problem of cross-language type-checking arises. This is difficult to solve in general.

14-6 In what ways can the naming of a specific destination process be avoided in a message system design? Why is this desirable?

By use of an indirection such as a channel name or global port name (that is, a port which is not bound to one specific process). This allows a number of anonymous processes to provide an equivalent service or for one process to be substituted for another one, perhaps on a failed component in a distributed system.

14-7 What is meant by multicast? What kind of naming service would be needed to support multicast?

A single SEND causes a multicast message to be sent to a list of recipients. It would be necessary to have a registration service so that names could be associated with groups, effectively distribution lists. A decision would have to be taken on whether lists are to be recursively structured, that is, can we have a component of list which is itself a list and so on. These issues are common at user level, in electronic mail services for example, but might become too heavyweight as part of an IPC mechanism.

A broadcast medium at the LAN level (such as Ethernet) provides a convenient optimisation of multicast. This is not the general case however.

The decision on whether to support multicast relates to application requirements and protocol design.

14-8 Why might it be important to be able to specify a limit on the time that one is prepared to wait for a message?

One might have other tasks to complete by a certain deadline or just alternative work to be getting on with.

There may not be a conditional wait and the timeout may fulfil this purpose. Perhaps there is no message and never will be, for example, one may have to check for an error condition periodically.

14-9 Use the Linda primitives introduced in Section 14.9 to program the interaction between a single centralised file server and its many clients.

The basic structure of a client and a server are:

server: in (S, who:name, in-formals )

[body of server S;

out ( who, out-actuals )

]

 

client call: out ( S, me, out-actuals ); % send request

in (me, in-formals); % get reply

Gelernter (1985), Carriero and Gelernter (1989), Andrews (1991) and Ben Ari (1990) give a number of Linda examples.