device_initialize() 関数が呼ばれる必要があります。各 I/O 要求には、どの I/O 操作が要求されているのかを表すタグがついています。このメインループでは、デバイスオープン要求用の IO_MESG_OPEN とデバイスシャットダウン要求用の IO_MESG_TERM だけが受け付けられます。
IO_MESG_OPEN 要求を受け取ると、デバイスサーバプロセスは実際の I/O 要求を処理する子プロセスを fotk します。
#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) は何もせず、読み込み要求は対応する I/O セルをゼロで埋めます。
#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;
}
}
}