An _IO_MSG message lets a client send an out-of-band or control message to a resource manager, by way of a file descriptor. This interface is more general than an ioctl() or devctl(), but less portable.
The format of the message is specific to the resource manager, aside from the header, which we'll look at shortly. The client program sets up the message and uses MsgSend() to send it to the resource manager. The resource manager must set up an io_msg handler in order to receive the message; there isn't a default handler.
The message header is defined in <sys/iomsg.h> and looks like this:
struct _io_msg { uint16_t type; uint16_t combine_len; uint16_t mgrid; uint16_t subtype; };
The fields include:
Any data should follow this header. For example:
typedef struct { struct _io_msg hdr; /* Add any required data fields here. */ } my_msg_t;
The client program would then do something like this:
#define MY_MGR_ID (_IOMGR_PRIVATE_BASE + 22) my_msg_t msg, my_reply; int fd; long status; fd = open ("/dev/sample", O_RDWR); msg.hdr.type = _IO_MSG; msg.hdr.combine_len = sizeof( msg.hdr ); msg.hdr.mgrid = MY_MGR_ID; msg.hdr.subtype = 0; /* Fill in the additional fields as required. */ status = MsgSend( fd, &msg, sizeof( msg ), &my_reply, sizeof (my_reply));
The resource manager registers a function to handle the _IO_MSG messages:
/* Initialize the functions for handling messages */ iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs, _RESMGR_IO_NFUNCS, &io_funcs); io_funcs.msg = my_io_msg;
This handler processes the message as appropriate. For example:
int my_io_msg (resmgr_context_t *ctp, io_msg_t *msg, RESMGR_OCB_T *ocb) { my_msg_t my_msg; MsgRead (ctp->rcvid, &my_msg, sizeof (my_msg), 0); if (my_msg.hdr.mgrid != MY_MGR_ID) { return (ENOSYS); } /* Process the data as required. */ /* Reply if necessary and tell the library that we've already replied. */ MsgReply( ctp->rcvid, 0, &my_reply, sizeof(my_reply)); return (_RESMGR_NOREPLY); }
Note that the handler returns ENOSYS if the mgrid member of the header isn't the correct manager ID. This handler replies to the client, and then returns _RESMGR_NOREPLY to tell the library that there's no need for it to do the reply.