device_initialize()
function should be
called. Each I/O request has a tag indicating which I/O operation is
requested. In this main loop, only IO_MESG_OPEN
for
device open request and IO_MESG_TERM
for device server
shutdown request are acceptable.
Upon receiving an IO_MESG_OPEN
request, a device server
process forks a child process in which actual I/O requests are
handled.
#include <score_device.h> int main( int argc, char **argv ) { struct sockaddr addr; pid_t pid; int addrsize; int fd; int tag; int cell; ioarg_t offset0, offset1; if(device_initialize(argc, argv) < 0) device_terminate( 3 ); device_log("Device Initialized !!"); while(1) { addrsize = sizeof(struct sockaddr); if((fd = accept(fd_listen, &addr, &addrsize)) < 0) { if(errno == EINTR) continue; /* in case of SIGCHLD */ device_log("Accept error"); device_terminate(1); } set_tcp_nodelay(fd); if(read_device_op( &tag, &cell, &offset0, &offset1, fd ) != 0) { device_log("Error in read device-op"); break; } switch(tag) { case IO_MESG_OPEN: if((pid = fork()) == 0) { /* if device process */ null_device(fd); } else if (pid > 0) { /* if device server process */ if(write_device_ack(fd, NORMAL_END, cell) != 0) { device_log("Error in write device ack"); } close(fd); } else { /* if error in fork() */ if(write_device_ack( fd, EIO, cell ) != 0) { device_log("Error in write device ack"); } device_log("Cannot fork device process"); } break; case IO_MESG_TERM: device_log("device shutdown"); device_terminate(0); break; default: device_log("Unknown I/O message tag (%d) (cell=%d,off=%d,wh=%d)", tag, cell, offset, whence); device_terminate(1); break; } } return(0); }
IO_MESG_WRITE
) is a no operation, and a
read request fills the corresponding I/O cell with zeros.
#include <score_device.h> void null_device (int fd) { int tag; int cell; ioarg_t offset0, offset1; char pseudo_dev[IO_BUFFER_SIZE]; char *iobuf; int length; while(1) { if(read_device_op( &tag, &cell, &offset0, &offset1, fd) != 0) { device_log("Error in read device-op"); device_terminate(1); } switch(tag) { case IO_MESG_WRITE: length = get_iocell(cell, &iobuf); /* actual write operation here */ if(write_device_ack(fd, NORMAL_END, cell) != 0) { device_log("Error in write device ack"); } break; case IO_MESG_READ: length = get_iocell(cell, &iobuf); bzero(iobuf, length); set_iocell_length(cell, length); if(write_device_ack(fd, NORMAL_END, cell) != 0) { device_log("Error in write device ack"); } break; case IO_MESG_CLOSE: if(write_device_ack( fd, NORMAL_END, cell) != 0) { device_log("Error in write device ack"); } close(fd); device_terminate(0); break; default: device_log("Unknown I/O message tag"); device_terminate(1); break; } } }