SCore-D デバイスドライバサンプルコード

このドキュメントでは単純な null デバイスを実現する SCore-D デバイスプログラムの例について記述しています。

デバイスサーバプロセス

デバイスプログラムの最初の部分は、デバイスオープン要求、またはデバイスシャットダウン要求を待つメインループです。main 関数の一番最初のほうで、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);
}

デバイスプロセス

デバイスプロセス内には、I/O 要求を待ち、要求を処理するループがあります。この例の null デバイスでは、書き込み要求 (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;
    }
  }
}

CREDIT
This document is a part of the SCore cluster system software developed at PC Cluster Consortium, Japan. Copyright (C) 2003 PC Cluster Consortium.