Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - Io Notify via file descriptor: (12 Items)
   
Io Notify via file descriptor  
I'd like to open "/dev/example-resmgr", then do an ionotify() to wait for input.
In case Input is available, I'd use MsgSend() to ask for the data, which the ResMgr's MsgReply will return to me.

Now according to the documentation I'd probably need to open a Channel, but that's not what I want, as I already got 
that fd that I'm using for communication. Or can I do SIGEV_PULSE_INIT() on the fd instead of the ConnectionID?

Another thing: I'm using this to transfer data structs. The structs vary wildly in size, which I don't know at compile 
time (don't ask...).  I could to a "read, read some more" by repeatedly asking for more using MsgSend() as long as a "
more" flag is set in the reply header..but i'd be much more elegant if I could read once and have the complete srtruct 
right away.
My idea now was to use the iofunc_notify_trigger() "len" parameter to signal the size of the next expected message. Will
 this work?
Will this work if several messages of differing sizes are triggered until the Client finds time to get them using 
MsgSend()? 

Thanks & Greetings,
 Marc
Re: Io Notify via file descriptor  
On Wed, Apr 15, 2009 at 10:03:25AM -0400, Marc Roessler wrote:
> I'd like to open "/dev/example-resmgr", then do an ionotify() to wait for input.
> In case Input is available, I'd use MsgSend() to ask for the data, which the ResMgr's MsgReply will return to me.
> 
> Now according to the documentation I'd probably need to open a Channel, but that's not what I want, as I already got 
that fd that I'm using for communication. Or can I do SIGEV_PULSE_INIT() on the fd instead of the ConnectionID?

You don't need to open a channel, just do the ionotify() on the fd you
already have and block in a manner such that the event you use in
ionotify() will wake you up.  Alternatively just use poll() which will
do both in the same call.

> 
> Another thing: I'm using this to transfer data structs. The structs vary wildly in size, which I don't know at compile
 time (don't ask...).  I could to a "read, read some more" by repeatedly asking for more using MsgSend() as long as a "
more" flag is set in the reply header..but i'd be much more elegant if I could read once and have the complete srtruct 
right away.
> My idea now was to use the iofunc_notify_trigger() "len" parameter to signal the size of the next expected message. 
Will this work?
> Will this work if several messages of differing sizes are triggered until the Client finds time to get them using 
MsgSend()? 

This isn't really clear to me.  If the client is calling read() it could
just read until the server returns eof.  If the client is writing the
server knows the size of the write and can MsgRead() as required.

-seanb
Re: Io Notify via file descriptor  
Ok So I'd do (shortened somewhat):
fd = open("/dev/example-resmgr", O_RDWR);
SIGEV_PULSE_INIT(&ioEvent, fd, ...);
ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &ioEvent);


Regarding the read(), this will not work for us. There may be several data structs waiting in the resmgr (in a queue) to
 be passed to the client, so the client won't receive EOF until they all have been consumed. This is bad, because this 
means that the client will now have all the structs concatenated into one big blob. Oops...
(Remember, the client does not know anything about the transported data structs! I could add a "length" header field 
that the client knows.. but then again, if I have no message borders, where is the advantage of using Message Passing - 
I could use tcp/ip just as well then, if i need to fish around to re-frame my data anyway...)

Greetings,
 Marc
Re: Io Notify via file descriptor  
On Wed, Apr 15, 2009 at 10:51:03AM -0400, Marc Roessler wrote:
> Ok So I'd do (shortened somewhat):
> fd = open("/dev/example-resmgr", O_RDWR);
> SIGEV_PULSE_INIT(&ioEvent, fd, ...);
> ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &ioEvent);

You can't use the same fd in SIGEV_PULSE_INIT that you send
on in ionotify.  How do you intend to block?  If you intend to 
call MsgReceive on your own channel then you can:

coid = ConnectAttach_r(ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0);

and use that coid in the SIGEV_PULSE_INIT.  If you're not blocking
in a MsgReceive on your own channel a pulse probably isn't what you
want.  As mentioned before poll() may be easier...

> 
> 
> Regarding the read(), this will not work for us. There may be several data structs waiting in the resmgr (in a queue) 
to be passed to the client, so the client won't receive EOF until they all have been consumed. This is bad, because this
 means that the client will now have all the structs concatenated into one big blob. Oops...

You'll have to segment them some how.  Maybe always have the client do a
read into a buffer big enough to hold the largest struct it'll ever get
and always reply with a full struct (datagram like) or EOF if there's
none left

> (Remember, the client does not know anything about the transported data structs! I could add a "length" header field 
that the client knows.. but then again, if I have no message borders, where is the advantage of using Message Passing - 
I could use tcp/ip just as well then, if i need to fish around to re-frame my data anyway...)
> 
> Greetings,
>  Marc
> 
> _______________________________________________
> OSTech
> http://community.qnx.com/sf/go/post27072
> 
Re: Io Notify via file descriptor  
> You can't use the same fd in SIGEV_PULSE_INIT that you send
> on in ionotify.
But isn't this exactly what select() does? One fd for reading and writing, and on that very fd we block?

> How do you intend to block? If you intend to 
> call MsgReceive on your own channel then you can:
> 
> coid = ConnectAttach_r(ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0);
How is this channel linked to the fd that I just opened then?
I don't intend to call MsgReceive on my channel, I'd just like to
wait (i.e. ionotify block) for messages from the server. When the server has a message for us, I'd ask for it using a 
MsgSend() message. Same as select/read, but with a different meaning for "read".

I could use select() just as well as poll(), correct?

> You'll have to segment them some how.  Maybe always have the client do a
> read into a buffer big enough to hold the largest struct it'll ever get
> and always reply with a full struct (datagram like) or EOF if there's
> none left
As I said, there is no upper limit. This is part of a framework with auto-generated code, and there really is no limit 
to the size of the data transferred (other than the length value must probably fit in 32bit).
Our messages already are segmented, it's multiple blobs of data queued once at a time. The irony is that we're losing 
this segmentation again when doing message passing (which is itself already segmented, as the name implies!).

That's how the idea came to use the pulse/notification to signal the size of the next message. The client then could 
allocate this amount of memory and call MsgSend(), knowing that the reply would fit into the buffer.

What do you think?

Greetings,
 Marc
Re: Io Notify via file descriptor  
On Wed, Apr 15, 2009 at 11:43:10AM -0400, Marc Roessler wrote:
> > You can't use the same fd in SIGEV_PULSE_INIT that you send
> > on in ionotify.
> But isn't this exactly what select() does? One fd for reading and writing, and on that very fd we block?

No it uses SIGEV_SIGNAL_THREAD and blocks in SignalWaitinfo().

> 
> > How do you intend to block? If you intend to 
> > call MsgReceive on your own channel then you can:
> > 
> > coid = ConnectAttach_r(ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0);
> How is this channel linked to the fd that I just opened then?

They're not really other than that you're using fd to send
the event to the server.  Pulses are sent to channels so if
you're not calling MsgReceive you can't use a pulse.

> I don't intend to call MsgReceive on my channel, I'd just like to
> wait (i.e. ionotify block) for messages from the server. When the server has a message for us, I'd ask for it using a 
MsgSend() message. Same as select/read, but with a different meaning for "read".
> 

I don't know what you mean by 'ionotify block'.

> I could use select() just as well as poll(), correct?

Sure, select() calls poll().

> 
> > You'll have to segment them some how.  Maybe always have the client do a
> > read into a buffer big enough to hold the largest struct it'll ever get
> > and always reply with a full struct (datagram like) or EOF if there's
> > none left
> As I said, there is no upper limit. This is part of a framework with auto-generated code, and there really is no limit
 to the size of the data transferred (other than the length value must probably fit in 32bit).
> Our messages already are segmented, it's multiple blobs of data queued once at a time. The irony is that we're losing 
this segmentation again when doing message passing (which is itself already segmented, as the name implies!).
> 
> That's how the idea came to use the pulse/notification to signal the size of the next message. The client then could 
allocate this amount of memory and call MsgSend(), knowing that the reply would fit into the buffer.
> 

> What do you think?

Sounds like it may be doable but again if you use a pulse
you'll have to MsgReceive it on a channel.  There also may
be a window where the ionotify() returns right away if
there's data available at the time of the call and no event
is armed in the server.

> 
> Greetings,
>  Marc
> 
> _______________________________________________
> OSTech
> http://community.qnx.com/sf/go/post27083
> 
Re: Io Notify via file descriptor  
> No it uses SIGEV_SIGNAL_THREAD and blocks in SignalWaitinfo().
select() uses _signals_? But wasn't select the parade example always mentioned when explaining why the QNX ionotify 
concept is so powerful? Actually even the printed material from the QNX training says that select() uses ionotify()?

> I don't know what you mean by 'ionotify block'.
This:
while ((r = ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &ioEvent)) > 0) {
   read(fd, ...);
}
ionotify() blocks until there is data available. Correct?

> Sounds like it may be doable but again if you use a pulse
> you'll have to MsgReceive it on a channel.
Ok.. let's suppose for a moment (just out of interest, for learning something) I'd use MsgReceive() on a channel.. how 
do I "link" that channel with the fd?
So far i know the following:
- ConnectionIDs are basically fds
- Connection(ID)s are created by ConnectAttach()ing a Channel
- I need a channel for receiving pulses
Combining this: when I have an fd, it means that the ConnectAttach() already has been done and I can use the fd for 
receiving Pulses..
If I'd really need to create a new channel for this, how would the server get access to this (now completely independent
 of the fd) channel?

Greetings,
 Marc




 right? Since Connections are based on Channels, and by ConnectAttach()ing a Channel I get a ConnectionID (which is 
basically an fd)
Re: Io Notify via file descriptor  
On Wed, Apr 15, 2009 at 12:28:52PM -0400, Marc Roessler wrote:
> > No it uses SIGEV_SIGNAL_THREAD and blocks in SignalWaitinfo().
> select() uses _signals_? But wasn't select the parade example always mentioned when explaining why the QNX ionotify 
concept is so powerful? Actually even the printed material from the QNX training says that select() uses ionotify()?

It uses SIGSELECT which is a synchronous signal, so like a
pulse without the need for a channel.

> 
> > I don't know what you mean by 'ionotify block'.
> This:
> while ((r = ionotify(fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &ioEvent)) > 0) {
>    read(fd, ...);
> }
> ionotify() blocks until there is data available. Correct?

Uh, no.  At least it shouldn't :)

> 
> > Sounds like it may be doable but again if you use a pulse
> > you'll have to MsgReceive it on a channel.
> Ok.. let's suppose for a moment (just out of interest, for learning something) I'd use MsgReceive() on a channel.. how
 do I "link" that channel with the fd?
> So far i know the following:
> - ConnectionIDs are basically fds
> - Connection(ID)s are created by ConnectAttach()ing a Channel
> - I need a channel for receiving pulses
> Combining this: when I have an fd, it means that the ConnectAttach() already has been done and I can use the fd for 
receiving Pulses..
> If I'd really need to create a new channel for this, how would the server get access to this (now completely 
independent of the fd) channel?
> 
> 
>  right? Since Connections are based on Channels, and by ConnectAttach()ing a Channel I get a ConnectionID (which is 
basically an fd)
> 

Again, you need a coid to your own channel, not the fd to the
server.  When the server does a MsgDeliverEvent(rcvid, &event)
the kernel pulls the scoid out of the rcvid which identifies
the client process, then finds the channel in said client based
on the coid in the event and delivers the pulse.  At least that's
my understanding...

Anyway, you've lots of options...

-seanb
Re: Io Notify via file descriptor  
> On Wed, Apr 15, 2009 at 12:28:52PM -0400, Marc Roessler wrote:
> > > No it uses SIGEV_SIGNAL_THREAD and blocks in SignalWaitinfo().
> > select() uses _signals_? But wasn't select the parade example always mentioned when explaining why the QNX ionotify 
concept is so powerful? Actually even the printed material from the QNX training says that select() uses ionotify()?
> 
> It uses SIGSELECT which is a synchronous signal, so like a
> pulse without the need for a channel.

To be clear it does use ionotify but instead of
SIGEV_PULSE as the event it uses SIGEV_SIGNAL_THREAD.

-seanb
Re: Io Notify via file descriptor  
> On Wed, Apr 15, 2009 at 11:43:10AM -0400, Marc Roessler wrote:
> > 
> > > You'll have to segment them some how.  Maybe always have the client do a
> > > read into a buffer big enough to hold the largest struct it'll ever get
> > > and always reply with a full struct (datagram like) or EOF if there's
> > > none left
> > As I said, there is no upper limit. This is part of a framework with auto-generated code, and there really is no 
limit to the size of the data transferred (other than the length value must probably fit in 32bit).
> > Our messages already are segmented, it's multiple blobs of data queued once at a time. The irony is that we're 
losing this segmentation again when doing message passing (which is itself already segmented, as the name implies!).
> > 
> > That's how the idea came to use the pulse/notification to signal the size of the next message. The client then could
 allocate this amount of memory and call MsgSend(), knowing that the reply would fit into the buffer.
> > 
> 
> > What do you think?
> 
> Sounds like it may be doable but again if you use a pulse
> you'll have to MsgReceive it on a channel.  There also may
> be a window where the ionotify() returns right away if
> there's data available at the time of the call and no event
> is armed in the server.

This also isn't standard in that the server would have to
alter the payload of the pulse.  A more 'standard' way would
be something like:

for (;;) {
	poll(&pfd, 1, -1);

	for (;;) {
		ioctl(fd, FIONREAD, &nread);
		if (nread == 0)
			break;
		if (nread > bufsize) {
			realloc(buf, nread);
			bufsize = nread;
		}
		read(fd, buf, nread);
	}
}

-seanb
Re: Io Notify via file descriptor  
> This also isn't standard in that the server would have to
> alter the payload of the pulse.

I fully agree.. this is all but standard.. we're not even using read(), we're using our own io_msg type messages, so the
 device will not be POSIX compliant anyway.
Re: Io Notify via file descriptor  
OK thanks for clearing up my misunderstandings!

So i will open a channel, advertise that channel to the server via ionotify (try & handle event until it actually 
succeeds in arming), then wait for pulses.

Concerning the idea of the server modifying/setting the pulse.value: besides being non-standard, are there any issues 
with this approach that I should be aware of?

Greetings,
 Marc