Since a large number of the messages received by a resource manager deal with a common set of attributes, the OS provides another level of default handling.
This second level, called the iofunc_*() shared library, allows a resource manager to handle functions like stat(), chmod(), chown(), and lseek() automatically, without the programmer having to write additional code. As an added benefit, these iofunc_*() default handlers implement the POSIX semantics for the messages, again offloading work from the programmer.
Three main structures need to be considered:
The first data structure, the context, has already been discussed (see the section on Message types). It holds data used on a per-open basis, such as the current position into a file (the lseek() offset).
Since 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 filesystem (block I/O device) managers, one more structure is used. This is the mount structure, which contains data items that are global to the entire mount device.
When a number of client programs have opened various devices on a particular resource, the data structures may look like this:
The iofunc_*() default functions operate on the assumption that the programmer has used the default definitions for the context block and the attributes structures. This is a safe assumption for two reasons:
By definition, the default structures must be the first members of their respective superstructures, allowing clean and simple access to the requisite base members by the iofunc_*() default functions:
The library contains iofunc_*() default handlers for these client functions: