The IO call can be used to simulate various styles of IPC. However, communication between client and server can be regarded as the native style, since that is essentially what classical I/O amounts to.
In (simple) client-server interaction, the server waits until it receives a request message. It then carries out the request, sends a reply message and waits for the next request. The client, on the other hand, is active until it sends a request after which it waits until it receives a reply.
Seen in terms of I/O, ``waiting'' is what happens in between initiating the I/O operation and completing it. Supposing that process A is the client and process B the server, we thus must have an initial state where B is already in the midst of an I/O operation using port Y, while A is free to execute.
When A finally needs to make a request to B, it performs an approriate I/O operation using port X. The IO call now packages the operation, address, out-len and in-len parameters supplied by A, as well as the byte string pointed to by out-buf into a message which is sent off to B. The receipt of the message now causes B to complete the I/O operation that it has been waiting to complete.
Moreover, the out values of the parameters B supplied when calling IO, is derived from the in values that A supplied when making its call to IO. Which is to say that the message received from A is unpacked into B's out parameters. The unpacking proceeds as follows:
Thus, B knows as much about A's ``I/O request'' as a file system would need to know, had A's request involved I/O from a file. B can thus serve A's request much like a file system would, and send its reply by performing another I/O operation using port Y. The initiation of this I/O operation by B, causes A to complete the I/O operation that it has been waiting for while B was executing. Furthermore, the out values of the parameters that A used for its I/O operation have been unpacked from the reply received from B. A can now carry on with execution while B waits for A's next request.
At a first reading, the above description may make IO sound too complicated for serious attention. However, it is worth noting that what complexity there is, lies mainly in writing servers. The programmer of a client process need not even be aware of using IO for IPC. To this programmer, the server process is a ``device'' that can be manipulated by means of classical I/O operations.
For example, a client process may open an IPC link to a name server and treat it as just another I/O device, except that this device has operations like store-name, retrieve-first-name, retrieve-next-name, etc., instead of operations like rewind, write-file-mark, skip-file-mark, etc. which a tape drive might offer. This is certainly just as simple as any other way of interacting with a name server.
In order to write server processes, one needs a more explicit understanding of how to use IO for IPC. Principally, one needs to become comfortable with the fact that the initiation of an I/O operation by one process can cause the completion of an in-progress I/O operation in another process. One also needs to become used to thinking of the in values of IO's parameters as a message sent to another process, which will receive it in the form of the out values of IO's parameters. Once this is understood, using IO as an IPC mechanism is not more difficult than using any other IPC mechanism.
Prof Herman Venter