Skip navigation.
Home
The QNX Community Portal

View topic - QNX6 interprocessing message

Page 1 of 1

QNX6 interprocessing message

PostPosted: Wed Apr 26, 2017 9:17 am
by keplerlima
Hello Im new in this forum and also new with QNX.
I did a basic program in c code for QNX4, related with interprocess communication.
The sender had to send one message and the receiver receive and reply, I know it is very basic stuff.
But now i changed to QNX6 and it seems different, I tried to make the same code in C with momentics 5.0 to communicate with
a Neutrino target in a virtual machine, but it doesn´t seem to work.
This is my new code:

////
#include <stdlib.h>
#include <stdio.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>

char sen_buf[40];
char rec_buf[40];
char rep_buf[40];

pid_t pid_sender;
pid_t pid_receiver;
int ret;

int main(int argc, char*argv[])

{

pid_receiver= qnx_name_locate ( 0, "Receiver", 0, NULL);

ret = Send (pid_receiver, sen_buf, rep_buf, sizeof(sen_buf), sizeof (rep_buf)),
if (ret (=!-1)
pid_sender = Receive(0, rec_buf, sizeof(rec_buf));

Reply(pid_sender, rep_buf, sizeof(rep_buf));

return 0;

}

I know its very basic thing, so maybe its not the right forum..
I know that I have to use qnx_name_attach and qnx_name_locate.

Hope you understand me,
Thanks in advance
Best regards.
Kepler lima

Re: QNX6 interprocessing message

PostPosted: Wed Apr 26, 2017 1:27 pm
by Tim
Did you start the 'nameloc'' process?

I believe this isn't started automatically in QNX 6 like it is in QNX 4 because QNX 6 uses different interprocess communication. The calls you are using were preserved in QNX 6 for porting QNX 4 code but you have to run nameloc.

Tim

Re: QNX6 interprocessing message

PostPosted: Wed Apr 26, 2017 3:04 pm
by maschoen
Adding to what Tim had to say...

I'd be very skeptical about what Receive(0,...) might try to do. The modern QNX 6 version should look like this:

int chid;
int rcvid;
struct _msg_info info;

chid = ChannelCreate(_NTO_CHF_SENDER_LEN);

rcvid = MsgReceive( chid, msg, size, &info);

MsgReply( rcvid, status, rmsg, size );

It might help to know why message passing has become more complex in QNX 6 to understand the differences.

The main issue is that QNX 6 supports threads. It is in principle possible for a process to use message passing to send and receive messages to itself. This means that a process is no longer in SEND/RECEIVE/REPLY mode, but rather its threads are. It is also possible that one wants to create a thread pool. This is a bunch of threads which all are in RECEIVE mode that can process messages as they come in.

So, taking a look at the code above, we see that before you can receive a message, you have to create a channel. A channel is known by all threads in a process. A process can have more than one channel. This allows more than one thread to be receive blocked on the same channel, and it also allows different threads to be blocked on different channels. You might ask which thread will receive a message if more than one is receive blocked on the same channel. I believe the answer is undefined. If you create a thread pool, any thread should be able to process the message.

A few other things before we go on to the sender side. The channel id (chid) is not a process id (pid).
The receive id (rcvid) is not a pid either. You should be used to the latter as even with QNX 2 the return from Receive() could have been
a virtual id when passing message over a network. This is somewhat hidden in QNX 6, however it is possible to learn what the node and pid of the sender is, note the _msg_info structure.

On the sender side the code looks like this. The terminology is confusingly similar to the sending side, but keep them straight.

int coid; // Connection Id
int ret;

coid = ConnectAttach( node, pid, chid, index, flags);

ret = MsgSend( coid, smsg, s_size, rmsg, r_size);

Here you get a connection id (coid) to the receiver and send using this coid, again not a pid.

What's wrong here? To create the coid you seem to need the node/pid/chid of the receiver. But how to you get it?
There is more than one way. Originally with QNX 6, all receivers needed to be resource managers that grabbed a piece
of name space, eg. /dev/myprogram. The sender would open() this name space and get the node/pid/chid from the fd returned. Note here that fd's and coid's are very similar in QNX 6.

Name space could of course be anywhere down the tree structure. It is even possible to grab already allocated name space. So for example,
you could have part of the file system as /database/file1. A database resource manager could grab /database so that an open to file1 would go to it and not the file system. It could then issue its own open() on file1, which would be processed by the file system giving it file access.

Getting back to coid's, after early releases, there were lots of complaints by users that having to implement the entire resource manager machinery was cumbersome. Reluctantly I think, QNX provided the name-attach/name-locate routines which do all the work. So the coid from a name attach is the same as from ConnectAttach().

So note that while rarely done, a sender could have multiple threads, each of which sends messages using different connections to a receiver with multiple threads where the receiver thread is controlled by having multiple channels.

Yes a lot more complex, but you can set things up simply, similar to QNX 4, which is often done. Also common is setting up a resource manager with a thread pool that can handle multiple requests at the same time. One nice thing about this is that with QNX 4 and 2 you alway had to either reply to a send or remember that the reply needed to be done in the future. With QNX 6 a thread can be allocated for each send, and that thread can be blocked without holding up other sends. A thread pool will allocate these threads dynamically. The can greatly simplify code. Of course you then need to implement synchronization of threads, usually with mutex's to prevent these threads from interfering.