/* start the resource manager message loop */
while(1) {
if((ctp = dispatch_block(ctp)) == NULL) {
fprintf(stderr, "block error\n");
return EXIT_FAILURE;
}
dispatch_handler(ctp);
}
Once the resource manager establishes its name, it receives messages when any client program tries to perform an operation (e.g., open(), read(), write()) on that name.
In our example, once /dev/sample is registered, and a client program executes:
fd = open ("/dev/sample", O_RDONLY);
the client's C library constructs an _IO_CONNECT message and sends it to our resource manager. Our resource manager receives the message within the dispatch_block() function. We then call dispatch_handler(), which decodes the message and calls the appropriate handler function based on the connect and I/O function tables that we passed in previously. After dispatch_handler() returns, we go back to the dispatch_block() function to wait for another message.
dispatch_context_t *ctp, *new_ctp;
ctp = dispatch_context_alloc( … );
while (1) {
new_ctp = dispatch_block( ctp );
if ( new_ctp ) {
ctp = new_ctp
}
else {
/* handle the error condition */
…
}
}
At some later time, when the client program executes:
read (fd, buf, BUFSIZ);
the client's C library constructs an _IO_READ message, which is then sent directly to our resource manager, and the decoding cycle repeats.