A bit of history

QNX Neutrino and our earlier QNX 4 RTOS both use a notion of Send/Receive/Reply for messaging. This IPC mechanism is (generally) used in a synchronous manner; the sending process waits for a reply from the receiver, and a receiver waits for a message to be sent. This provides a very easy call-response synchronization.

Under QNX 4, the Send() function needed only the process ID (pid) of the receiving process. QNX 4 also provided a very simple API for giving a process a name and, in turn, looking up that name to get a process ID. So you could name your server process, and then your client process could look up that name, get a process ID (pid), and then send the server some data and wait for a reply. This model worked well in a non-threaded environment.

Since QNX Neutrino includes proper thread support, the notion of having a single conduit into a process doesn't make a lot of sense, so a more flexible system was designed. To perform a MsgSend() under QNX Neutrino, you no longer need a pid, but rather a connection ID (coid).

This coid is obtained from opening a connection to a channel. Processes can create multiple channels and can have different threads service any (or all) of them. The issue now becomes: how does a client get a coid in the first place so it can open a connection to get the coid it needs to perform the MsgSend()?

There are many different ways this kind of information-sharing can occur, but the method that falls in line with the QNX Neutrino design ideals is for the server to also be a resource manager.

Under QNX Neutrino — and other POSIX systems — when you call open(), you get back a file descriptor (fd). But this fd is also a coid. So instead of registering a name, as in QNX 4, your server process registers a path in the filesystem, and the client opens that path to get the coid to talk to the server.