26.02.2014 Views

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

© 2009, <strong>QNX</strong> <strong>Software</strong> <strong>Systems</strong> GmbH & Co. KG. Examples<br />

Step 7<br />

Step 8<br />

Step 9<br />

Now we advance the lseek() offset by the number of bytes that we returned to the<br />

client, only if we are not processing the _IO_XTYPE_OFFSET override modifier. This<br />

ensures that, in the non-_IO_XTYPE_OFFSET case, if the client calls lseek() to get the<br />

current position, or (more importantly) when the client calls read() to get the next few<br />

bytes, the offset into the resource is set to the correct value. In the case of the<br />

_IO_XTYPE_OFFSET override, we leave the ocb version of the offset alone.<br />

Contrast step 6 <strong>with</strong> this step. Here we only unblock the client, we don’t perform any<br />

other functions. Notice also that there is no data area specified to the MsgReply(),<br />

because we’re not returning data.<br />

Finally, in step 9, we perform processing that’s common regardless of whether or not<br />

we returned data to the client. Since we’ve already unblocked the client via the<br />

MsgReply(), we certainly don’t want the resource manager library doing that for us, so<br />

we tell it that we’ve already done that by returning _RESMGR_NOREPLY.<br />

Effective use of other messaging functions<br />

A simple io_write() example<br />

As you’ll recall from the Message Passing chapter, we discussed a few other<br />

message-passing functions — namely MsgWrite(), MsgWritev(), and MsgReplyv().<br />

The reason I’m mentioning them here again is because your io_read() function may<br />

be in an excellent position to use these functions. In the simple example shown above,<br />

we were returning a contiguous array of bytes from one memory location. In the real<br />

world, you may need to return multiple pieces of data from various buffers that you’ve<br />

allocated. A classical example of this is a ring buffer, as might be found in a serial<br />

device driver. Part of the data may be near the end of the buffer, <strong>with</strong> the rest of it<br />

“wrapped” to the top of the buffer. In this case, you’ll want to use a two-part IOV <strong>with</strong><br />

MsgReplyv() to return both parts. The first part of the IOV would contain the address<br />

(and length) of the bottom part of the data, and the second part of the IOV would<br />

contain the address (and length) of the top part of the data. Or, if the data is going to<br />

arrive in pieces, you may instead choose to use MsgWrite() or MsgWritev() to place<br />

the data into the client’s address space as it arrives and then specify a final MsgReply()<br />

or MsgReplyv() to unblock the client. As we’ve seen above, there’s no requirement to<br />

actually transfer data <strong>with</strong> the MsgReply() function — you can use it to simply<br />

unblock the client.<br />

The io_read() example was fairly simple; let’s take a look at io_write(). The major<br />

hurdle to overcome <strong>with</strong> the io_write() is to access the data. Since the resource<br />

manager library reads in a small portion of the message from the client, the data<br />

content that the client sent (immediately after the _IO_WRITE header) may have only<br />

partially arrived at the io_write() function. To illustrate this, consider the client writing<br />

one megabyte — only the header and a few bytes of the data will get read by the<br />

April 30, 2009 Chapter 5 • Resource Managers 259

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!