Writing a resource manager is by far the most complicated task that we've discussed in this book.

A resource manager is a server that receives certain, well-defined messages. These messages fall into two broad categories:

Connect messages
Related to pathname-based operations, these may establish a context for further work.
I/O messages
Always arrive after a connect message and indicate the actual work that the client wishes to have done (e.g., stat()).

The operations of the resource manager are controlled by the thread pool functions (discussed in the Processes and Threads chapter) and the dispatch interface functions.

QNX Neutrino provides a set of POSIX helper functions in the resource manager library that perform much of the work of dealing with the client's Connect and I/O messages that arrive.

There are a number of data structures relating to the clients and devices manifested by the resource manager to keep in mind:

Allocated on a per-open basis, this contains the context for the client (e.g., current lseek() position)
Attributes structure
Allocated on a per-device basis, this contains information about the device (e.g., size of the device, permissions, etc.)
Mount structure
Allocated on a per-resource-manager basis, and contains information about the characteristics of the entire resource manager.

The clients communicate with the resource manager via message passing by resolving the pathname (via the open() and other calls) into a node descriptor, process ID, channel ID, and handle.

Finally you supply the functionality you wish to actually do in your resource manager by overriding some of the callouts in the Connect and I/O functions table.