Messages that should be connect messages but aren't

QNX SDP8.0Getting Started with the QNX OSDeveloperUser

Here's an interesting point you may have noticed. Consider the client's prototype for chown() shown below.

int chown (const char *path,
           uid_t owner,
           gid_t group);

Remember, a connect message always contains a pathname and is either a one-shot message or establishes a context for further I/O messages.

So, why isn't there a connect message for the client's chown() function? In fact, why is there an I/O message?!? There's certainly no file descriptor implied in the client's prototype!

The answer is, to make your life simpler!

Imagine if functions like chown(), chmod(), stat(), and others required the resource manager to look up the pathname and then perform some kind of work. (This is, by the way, the way it was implemented in QNX 4.) The usual problems with this are:

  • Each function has to call the lookup routine.
  • Where file descriptor versions of these functions exist, the driver has to provide two separate entry points; one for the pathname version, and one for the file descriptor version.
In any event, what happens under QNX OS is that the client constructs a combine message—really just a single message that comprises multiple resource manager messages. Without combine messages, we could simulate chown() with something like this:
int chown (const char *path, uid_t owner, gid_t group)
{
    int fd, sts;

    if ((fd = open (path, O_RDWR)) == -1) {
        return (-1);
    }
    sts = fchown (fd, owner, group);
    close (fd);
    return (sts);
}

Here, fchown() is the file-descriptor-based version of chown(). The problem here is that we are now issuing three function calls (and three separate message passing transactions), and incurring the overhead of open() and close() on the client side.

With combine messages, under QNX OS a single message that looks like this is constructed directly by the client's chown() library call:
Figure 1A combine message.

Combine message

The message has two parts, a connect part (similar to what the client's open() would have generated) and an I/O part (the equivalent of the message generated by the fchown()). There is no equivalent of the close() because we implied that in our particular choice of connect messages. We used the _IO_CONNECT_COMBINE_CLOSE message, which effectively states Open this pathname, use the file descriptor you got for handling the rest of the message, and when you run off the end or encounter an error, close the file descriptor.

The resource manager that you write doesn't have a clue that the client called chown() or that the client did a distinct open(), followed by an fchown(), followed by a close(). It's all hidden by the base-layer library.

Page updated: