![]() |
![]() |
![]() |
Register a name in the namespace and create a channel
#include <sys/dispatch.h> name_attach_t * name_attach( dispatch_t * dpp, const char * path, unsigned flags );
libc
The name_attach(), name_close(), name_detach(), and name_open() functions provide the basic pathname- to server-connection mapping, without having to become a full resource manager.
![]() |
This functionality is provided for compatibility with QNX 4-style programs; for QNX 6 applications, we recommend that you use the resource manager framework. For more information, see the "Writing a Resource Manager" chapter in the Programmer's Guide. |
A dispatch structure is created for you automatically if you pass NULL as the dpp. If you've already created a dispatch structure, pass it in as the dpp. If you provide your own dpp, set flags to NAME_FLAG_DETACH_SAVEDPP when calling name_detach(); otherwise, your dpp is detached and destroyed automatically.
The name_attach() function puts the name path into the path namespace under /dev/name/[local|global]/path. The name shouldn't contain any .. characters or start with a leading slash /. The name is attached locally by default, or globally when flags is set to NAME_FLAG_ATTACH_GLOBAL. You can see attached names in /dev/name/local and /dev/name/global directories (global names aren't supported yet).
ChannelCreate() is called with the _NTO_CHF_UNBLOCK, _NTO_CHF_DISCONNECT, and _NTO_CHF_COID_DISCONNECT flags set. The _NTO_CHF_THREAD_DEATH flag isn't passed to ChannelCreate(), but is implied by the setting of _NTO_CHF_COID_DISCONNECT. Therefore, your server that's using name_attach() may receive pulses as described in ChannelCreate. For instance, since _NTO_CHF_DISCONNECT is set, when a client calls name_close() you'll receive the _PULSE_CODE_DISCONNECT pulse message.
For more information on the pulses (a rcvid of 0) related to the _NTO_CHF_COID_DISCONNECT, _NTO_CHF_DISCONNECT, _NTO_CHF_THREAD_DEATH and the _NTO_CHF_UNBLOCK flags, see ChannelCreate().
If the receive buffer which the server provides isn't large enough to hold a pulse, then MsgReceive() returns -1 with errno set to EFAULT.
The name_attach_t data structure is returned from the name_attach() call. It looks like this:
#include <sys/dispatch.h> typedef struct _name_attach { dispatch_t* dpp; int chid; int mntid; int zero[2]; } name_attach_t;
where
The information that's generally required by a server using these services is the chid.
The name_attach_t structure filled in, or NULL if the call fails (errno is set).
#include <stdio.h> #include <errno.h> #include <stdlib.h> #include <sys/dispatch.h> #define ATTACH_POINT "myname" /* We specify the header as being at least a pulse */ typedef struct _pulse msg_header_t; /* Our real data comes after the header */ typedef struct _my_data { msg_header_t hdr; int data; } my_data_t; /*** Server Side of the code ***/ int server() { name_attach_t *attach; my_data_t msg; int rcvid; /* Create a local name (/dev/name/local/...) */ if ((attach = name_attach(NULL, ATTACH_POINT, 0)) == NULL) { return EXIT_FAILURE; } /* Do your MsgReceive's here now with the chid */ while (1) { rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL); if (rcvid == -1) {/* Error condition, exit */ break; } if (rcvid == 0) {/* Pulse received */ switch (msg.hdr.code) { case _PULSE_CODE_DISCONNECT: /* * A client disconnected all its connections (called * name_close() for each name_open() of our name) or * terminated */ ConnectDetach(msg.hdr.scoid); break; case _PULSE_CODE_UNBLOCK: /* * REPLY blocked client wants to unblock (was hit by * a signal or timed out). It's up to you if you * reply now or later. */ break; default: /* * A pulse sent by one of your processes or a * _PULSE_CODE_COIDDEATH or _PULSE_CODE_THREADDEATH * from the kernel? */ } continue; } /* A QNX IO message received, reject */ if (msg.hdr.type >= _IO_BASE && msg.hdr.type <= _IO_MAX) { MsgError(rcvid, ENOSYS); continue; } /* A message (presumable ours) received, handle */ printf("Server receive %d \n", msg.data); MsgReply(rcvid, EOK, 0, 0); } /* Remove the name from the space */ name_detach(attach, 0); return EXIT_SUCCESS; } /*** Client Side of the code ***/ int client() { my_data_t msg; int fd; if ((fd = name_open(ATTACH_POINT, 0)) == -1) { return EXIT_FAILURE; } /* We would have pre-defined data to stuff here */ msg.hdr.type = 0x00; msg.hdr.subtype = 0x00; /* Do whatever work you wanted with server connection */ for (msg.data=0; msg.data < 5; msg.data++) { printf("Client sending %d \n", msg.data); if (MsgSend(fd, &msg, sizeof(msg), NULL, 0) == -1) { break; } } /* Close the connection */ name_close(fd); return EXIT_SUCCESS; } int main(int argc, char **argv) { int ret; if (argc < 2) { printf("Usage %s -s | -c \n", argv[0]); ret = EXIT_FAILURE; } else if (strcmp(argv[1], "-c") == 0) { printf("Running Client ... \n"); ret = client(); /* see name_open() for this code */ } else if (strcmp(argv[1], "-s") == 0) { printf("Running Server ... \n"); ret = server(); /* see name_attach() for this code */ } else { printf("Usage %s -s | -c \n", argv[0]); ret = EXIT_FAILURE; } return ret; }
Safety: | |
---|---|
Cancellation point | Yes |
Interrupt handler | No |
Signal handler | No |
Thread | Yes |
As a server, you shouldn't assume that you're doing a MsgReceive() on a clean channel. In QNX 6 (and QNX 4) anyone can create a random message and send it off to a process or a channel.
We recommend that you do the following to assure that you're playing safely with others in the system:
#include <sys/neutrino.h> /* All of your messages should start with this header */ typedef struct _pulse msg_header_t; /* Now your real data comes after this */ typedef struct _my_data { msg_header_t hdr; int data; } my_data_t;
where
ChannelCreate(), dispatch*() functions, MsgReceive(), name_detach(), name_open(), name_close(), resmgr_attach()
![]() |
![]() |
![]() |