The Möbius Operating System: Inter-Process Communication

Inter-Process Communication

Tim Robinson


This document describes the forms of inter-process communication available to Möbius applications programmers, and provides an overview of the functionality and implementation of each.

The Möbius provides three main forms of IPC:

  • ports,
  • shared memory, and
  • GUI messages

Note: Although the overall design of these features is unlikely to change in future releases, the implementation and minor design points are. The IPC implementation has also not been fully tested in current releases.


Source: kernel/port.c, console/console.c

Ports in The Möbius are most similar to sockets in other operating systems. Ports are separated into server and client ports.

Client ports, once connected to a server port, can be read from and written to like any other file. They are created by creating or opening a file in the ports directory (by default, /System/Ports). It is the responsibility of the client task to keep track of client port handles, as with any other file object. Server ports can neither be read from nor written to. Server ports start out as unconnected client ports; they gain their server status when the server task calls PortListen. Server ports are kept track of by the port file system, and their names are stored in a global list. A server port handle become signalled each time a client connects to it. A typical client-server interaction using ports is as follows.

  1. The server creates a server port by creating a file in the /System/Ports directory with a name that is known to the client.
  2. The server calls PortListen on the handle returned from FsCreate.
  3. The server calls ThrWaitHandle on the port handle to wait for a connection.
  4. The client opens the server port by opening the correct file in the /System/Ports directory. The port is automatically connected to the server.
  5. The server completes its wait; it knows that a client has attempted to connect. It calls PortAccept to accept the connection, which creates another client port. The server's client port and the client's client port are connected together so that writes from one go to the other. The server's server port continues to accept new connections, if necessary.
  6. The client and server are now free to read from and write to their respective client ports. Once each has finished it will call FsClose, as normal, to close the handle.
  7. Client ports maintain an internal buffer. When the remote task writes to a port connected to a port owned by the local task, it copies data into the local task's buffer until the buffer is full. The data in the local task's buffer can then be read by the local task using FsRead or FsReadSync.

Ports support asynchronous I/O, as do most types of file object in The Möbius. Reads will block until there are as many bytes in the port's buffer as required by the read; write will block if the write would go past the end of the buffer. Client-to-server connections are also asynchronous, even though they are made using the synchronous FsOpen. Assuming that the parameters are correct (i.e. the server port exists), FsOpen will signal the server port and return immediately without error. However, it could be some time before the server task can service the request and call PortAccept. Therefore, the first read or write request on a client port will block until the port is fully connected. If the connection failed, the first read or write request will fail because of that (and not because of some I/O error). If a guaranteed connect is required then it is possible to call FsOpen followed by a zero-byte FsRead to verify the connection. If either calls fail then the connection has failed; otherwise, the client is free to send and receive data through the port.

3.Shared Memory

Source: kernel/vmm.c

Although the required framework is present in the kernel, shared memory is not currently made available to user applications.

4.GUI Messages

Source: kernel/winmgr.c, gui/window.cpp

Messages are the main method of inter-process and inter-thread communication in the Möbius GUI. Messages are fixed-length structures containing a 32-bit code, a target window handle and three general-purpose 32-bit parameters.

Messages are received in the message loops of GUI threads, and are generated either in the kernel window manager, in response to external events such as user input or window invalidation, or by other threads or processes. Each GUI thread has a kernel message queue, which expands to contain any messages sent to a window owned by the thread but not handled. Messages are removed from the queue when handled.

Normally the GUI programmer would not need to deal with messages directly: system-defined messages are handled by Window::HandleMessage and directed to the appropriate virtual member function. However, messages can make a handy form of inter-thread or inter-process notification: Window::PostMessage can be used to post messages to a window in the same process, and xxx - some_function_i_havent_written_yet can post messages between processes. To handle a custom message, or redefine the behaviour of an existing one, override Window::HandleMessage.

xxx - should be possible to post messages to threads as well.

Post a comment