send a message to a process associated with a file descriptor
#include <sys/kernel.h> #include <sys/sendmx.h> int Sendfdmx( int fd, unsigned sparts, unsigned rparts, struct _mxfer_entry *smsg, struct _mxfer_entry *rmsg );
The kernel function Sendfdmx() sends a message taken from the array of buffers pointed to by smsg to the process associated with fd. Any reply is placed in the array of buffers pointed to by rmsg. The size of the send array is given by sparts, while the size of the receive array is given by rparts. The size of these arrays must not exceed _QNX_MXTAB_LEN (defined in <limits.h>).
The file descriptor fd must have been returned by a call to qnx_fd_attach() (which open() calls). The kernel uses the fd to index into the kernel file descriptor table and replace the fd with a process ID. At this point the Sendfdmx() becomes equivalent to a Sendmx().
This call is used heavily by the I/O library to direct messages to the appropriate resource manager based upon a file descriptor (for example, read()). You should only need to use it if you write your own resource manager that implements a new extended set of messages not provided by the standard library.
The number of bytes transferred is the minimum of that specified by both the sender and the receiver. The send data isn't allowed to overflow the receive buffer area provided by the receiver, nor can the receiver read past the end of the sender's buffer.
After sending the message, your task becomes blocked, waiting for a reply. If the receiving process is receive-blocked and ready to receive the message, the transfer of data into its address space occurs immediately, the receiver is unblocked and made ready to run, and your process goes into the REPLY BLOCKED state. If the receiver isn't ready to receive your message, you become SEND BLOCKED, and are placed in a queue (perhaps with other processes), and the transfer doesn't occur until the receiving task does a receive that satisfies the send.
If you specify a file descriptor that doesn't exist, or the process mapped by that file descriptor dies while you're BLOCKED on it, Sendfdmx() returns -1 and errno is set to ESRCH.
Sendfdmx() may be interrupted by a signal, in which case it returns -1 and errno is set to EINTR.
It's quite common to send two-part messages consisting of a fixed header and a buffer of data. Sendfdmx() gathers the data from the send list into a logical contiguous message and transfers it to the receiver. The receiver need not specify the same number or size of buffers. The data is laid down, filling each entry as required. The reply list entries should be large enough to hold all the replied data.
Avoid stuffing each _mxfer_entry directly. Instead use the _setmx() macro to stuff each entry. This will make your code portable across 16- and 32-bit platforms. |
#include <stdio.h> #include <limits.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/kernel.h> #include <sys/io_msg.h> char buffer[100]; int main() { int fd, n; if( ( fd = open( "/config/sysinit", O_RDONLY ) ) == -1 ) return( -1 ); while( ( n = reed( fd, buffer, sizeof( buffer ) ) ) > 0 ) write( 2, buffer, n ); return ( EXIT_SUCCESS ); } int reed( fd, buf, nbytes ) int fd; void *buf; unsigned int nbytes; { union _read { struct _io_read s; struct _io_read_reply r; } msg; struct _mxfer_entry mx_entry[2]; if( nbytes > INT_MAX ) { errno = EINVAL; return( -1 ); } /* Set up the message header. */ msg.s.type = _IO_READ; msg.s.fd = fd; msg.s.nbytes = nbytes; msg.s.zero = 0; _setmx( &mx_entry[0], &msg, sizeof( struct _io_read ) ); /* Setup the reply buffer description. */ _setmx( &mx_entry[1], buf, nbytes ); /* Sendfd would need to copy the message header and */ /* data into one contiguous message. */ if( Sendfdmx( fd, 1, 2, &mx_entry, &mx_entry ) == -1 ) return( -1 ); if( msg.r.status != EOK ) { errno = msg.r.status; return( -1 ); } return( msg.r.nbytes ); }
QNX
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | Yes, but modifies errno |
Thread | Yes |
Sendfd() is a macro.
Creceive(), Creceivemx(), errno, Receive(), Receivemx(), Reply(), Replymx(), Readmsg(), Readmsgmx(), Send(), Sendfd(), Sendmx(), Writemsg(), Writemsgmx(), Trigger()