QNX Resource Managers

Neutrino resource managers are responsible for presenting an interface to various types of devices. This may involve managing actual hardware
devices (like serial ports, parallel ports, network cards, and disk drives) or virtual devices (like /dev/null, a network filesystem, and pseudo-ttys).

In other operating systems, this functionality is traditionally associated with device drivers. But unlike device drivers, Neutrino's resource managers
don't require any special arrangements with the kernel. In fact, a resource manager looks just like any other user-level program.
 

Resource manager architecture

Here is the heart of a resource manager:

initialize the dispatch interface
register the pathname with the process manager
DO forever
    receive a message
    SWITCH on the type of message
        CASE io_open:
            perform io_open processing
            ENDCASE
        CASE io_read:
            perform io_read processing
            ENDCASE
        CASE io_write:
            perform io_write processing
            ENDCASE
        .   // etc. handle all other messages
        .   // that may occur, performing
        .   // processing as appropriate
    ENDSWITCH
ENDDO

The architecture contains three parts:

  1.A channel is created so that client programs can connect to the resource manager to send it messages.
  2.The pathname (or pathnames) that the resource manager is going to be responsible for is registered with the process manager, so that it can
    resolve open requests for that particular pathname to this resource manager.
  3.Messages are received and processed.

Note:  The library can hide lots of this.  You don't have to write the loop.  You can just register handlers, and each handler
gets called when the right message comes.  Rather like Java mouseEvents.

What's not in the resource manager?

The Possible Messages

Contexts are much more like 'struct file *' and rather less like a file descriptor.  The difference is that contexts are a structure with many fields.

What they give you for free

There is a shared library that offers thinks like dup() and lseek().  There is a set of functions that returns ENOSYS.

Combined Messages
Exchanging lots of little messages can be slow.  Much nicer is to group the messages into a single exchange.  For example, a stat() is the group open(), fstat(), close().  Readblock() is seek(), read().  The standard resource manager library recieves a group, and breaks it into each message for you.  You just recieve the individual messages, and have no idea they are part of a group.
 

Resource Manager Data Structures

A resource manager is responsible for three data structures.

The first data structure is the context,  It holds data used on a per-open basis, such as the current position into a file (the lseek() offset).

Because a resource manager may be responsible for more than one device (e.g. devc-ser* may be responsible for /dev/ser1, /dev/ser2,
/dev/ser3, etc.), the attributes structure holds data on a per-device basis. The attributes structure contains such items as the user and group ID of
the owner of the device, the last modification time, etc.

For block I/O devices, one more structure is used. This is the mount structure, which contains data items that are global to the entire mount device.

The library assumes that you use the default structure types.  You can add new members (AT THE BOTTOM) but not delete any mambers.  Each member must have the standard semantics.  Therfore f_pos better be in bytes, not blocks.

Code for a Resource Manager

See the qnx documentation at http://qdn.qnx.com/support/docs/neutrino_2.11_en/prog/resmgr.html#SIMPLE_ST_EG