Messages that should be connect messages but aren't
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.
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.
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.