[Previous]
[Contents]
[Next]

Send()

send a message to a process

Synopsis:

#include <sys/kernel.h>
int Send( pid_t pid,
          void *smsg, void *rmsg,
          unsigned snbytes, unsigned rnbytes );

Description:

The kernel function Send() sends a message pointed to by smsg to the process identified by pid. Any reply is placed in the message buffer pointed to by rmsg. The maximum size of the sent message is snbytes, while the size of the reply is truncated to a maximum of rnbytes.

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 a message, the 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 the sending process enters the REPLY BLOCKED state. If the receiver isn't ready to receive your message, the sending task becomes SEND BLOCKED and is placed in a queue (perhaps with other processes), and the transfer doesn't occur until the receiving task executes a receive.

If a process is specified that doesn't exist, or that dies while the sending process is BLOCKED on it, Send() returns -1, and errno is set to ESRCH.

Send() may be interrupted by a signal, in which case it returns -1, and errno is set to EINTR.

Send() is a simple cover function that builds two single-part _mxfer_entry structures on the stack, and calls Sendmx(), which is the real kernel function. Send() is provided for convenience since it's easier to use than Sendmx() for simple messages.

Returns:

0
Success.
-1
An error occurred. errno is set to indicate the error.

Errors:

EAGAIN
No more Process Manager to Network Manager queue packets available.
EDSTFAULT
Destination would fault on a message pass.
EFAULT
In order to complete the message exchange, the current process would have incurred a segment violation. Your buffer(s) may be invalid or too small.
EHOSTUNREACH
The destination node isn't in the net mapping, or a physical I/O error occurred trying to communicate to the node.
EINTR
Call interrupted by a signal.
EINVAL
The virtual circuit buffer cannot be grown due to an invalid message length.
ENOMEM
The virtual circuit buffer cannot be grown because no memory is available.
ESRCH
The process pid doesn't exist.

Examples:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/kernel.h>

/* Define all messages that are sent and replied */

#define PRINT     1
#define LOWER     2
#define STOP      3

/* The sizeof(type) == sizeof(status) in all messages */
struct msg_print {
  short unsigned type;
  char         string[81];
  } ;

struct msg_print_reply {
  short unsigned status;
  } ;

struct msg_lower {
  short unsigned type;
  char         string[81];
  } ;

struct msg_lower_reply {
  short unsigned status;
  char         string[81];
  } ;

struct msg_stop {
  short unsigned type;
  } ;

struct msg_stop_reply {
  short unsigned status;
  } ;

/* Define the union of all messages */
union {
  short unsigned          type;
  short unsigned          status;
  struct msg_print        print;
  struct msg_print_reply  print_reply;
  struct msg_lower        lower;
  struct msg_lower_reply  lower_reply;
  struct msg_stop         stop;
  struct msg_stop_reply   stop_reply;
  } msg;


int main( void )
  {
    pid_t child;

    if( child = fork() )
      client( child );
    else
      server();

    exit( EXIT_SUCCESS );
  }


void server()
  {
    pid_t pid;
    char *cp;
    unsigned nbytes;

    for( ;; ) {
      pid = Receive( 0, &msg, sizeof( msg ) );
      nbytes = sizeof( msg.status );

      switch( msg.type ) {
        case PRINT:
          printf( "Server PRINT %s\n", msg.print.string );
          msg.print_reply.status = EOK;
          break;

        case LOWER:
          printf( "Server LOWER %s\n", msg.lower.string );
          for( cp = msg.lower.string ; *cp ; ++cp )
            *cp = tolower (*cp);
          nbytes += strlen( msg.lower.string );
          msg.lower_reply.status = EOK;
          break;

        case STOP:
          /* Note that for this example we terminate */
          /* without replying to show that the */
          /* client Send unblocks. */
          printf( "Server STOP\n" );
          return;

        default:
          printf( "Server unknown message %04X\n",
            msg.type );
          msg.status = ENOSYS;
          break;
      }

      Reply( pid, &msg, nbytes );
    }
  }


void client( child )
pid_t child;
  {
    int r;

    printf( "Client PRINT\n" );
    msg.print.type = PRINT;
    strcpy( msg.print.string, "Hello world!" );
    r = Send( child, &msg.print, &msg.print_reply,
         sizeof( msg.print ), sizeof( msg.print_reply ) );
    printf( "Client PRINT %d %d\n\n", r,
         msg.print_reply.status );

    printf( "Client LOWER\n" );
    msg.lower.type = LOWER;
    strcpy( msg.lower.string, "Hello world!" );
    r = Send( child, &msg.lower, &msg.lower_reply,
         sizeof( msg.lower ), sizeof( msg.lower_reply ) );
    printf( "Client LOWER %d %d ", r,
         msg.lower_reply.status );
    printf( "%s\n\n", msg.lower_reply.string );

    printf( "Client ???\n" );
    msg.type = 100;
    r = Send( child, &msg.type, &msg.status,
         sizeof( msg.type ), sizeof( msg.status ) );
    printf( "Client ??? %d %d\n\n", r, msg.status );

    printf( "Client STOP\n" );
    msg.stop.type = STOP;
    r = Send( child, &msg.stop, &msg.stop_reply,
         sizeof( msg.stop ), sizeof( msg.stop_reply ) );
    printf( "Client STOP %d %d\n", r,
         msg.stop_reply.status );
  }

produces the output:

Client PRINT
Server PRINT Hello world!
Client PRINT 0 0

Client LOWER
Server LOWER Hello world!
Client LOWER 0 0 hello world!

Client ???
Server unknown message 0064
Client ??? 0 89

Client STOP
Server STOP
Client STOP -1 3

Classification:

QNX

Safety:
Interrupt handler No
Signal handler Yes, but modifies errno
Thread Yes

Caveats:

Send() is a macro.

See also:

Creceive(), Creceivemx(), errno, Receive(), Receivemx(), Reply(), Replymx(), Readmsg(), Readmsgmx(), Sendfd(), Sendfdmx(), Sendmx(), Writemsg(), Writemsgmx(), Trigger()


[Previous]
[Contents]
[Next]