デバイステーブル(devtab)

bindmount関数からcmount関数にも出てきたが,devtabというデータ構造も重要っぽい.devtabはDev構造体の配列で,そのインデックスはチャネルのタイプになっている.そして,チャネルへの操作は次のように,devtab経由で間接呼出しすることになる.

port/devcons.c
  310: int
  311: pprint(char *fmt, ...)
  312: {

  321:         c = up->fgrp->fd[2];

  331:         devtab[c->type]->write(c, buf, n, c->offset);

Dev構造体は次の通り,中身は関数ポインタテーブルである.抽象データ型というか,UNIXでいうところのVFSみたいだなぁ.

port/portdat.h
  197: struct Dev
  198: {
  199:         int    dc;
  200:         char*  name;
  201: 
  202:         void   (*reset)(void);
  203:         void   (*init)(void);
  204:         void   (*shutdown)(void);
  205:         Chan*  (*attach)(char*);
  206:         Walkqid*(*walk)(Chan*, Chan*, char**, int);
  207:         int    (*stat)(Chan*, uchar*, int);
  208:         Chan*  (*open)(Chan*, int);
  209:         void   (*create)(Chan*, char*, int, ulong);
  210:         void   (*close)(Chan*);
  211:         long   (*read)(Chan*, void*, long, vlong);
  212:         Block* (*bread)(Chan*, long, ulong);
  213:         long   (*write)(Chan*, void*, long, vlong);
  214:         long   (*bwrite)(Chan*, Block*, ulong);
  215:         void   (*remove)(Chan*);
  216:         int    (*wstat)(Chan*, uchar*, int);
  217:         void   (*power)(int);    /* power mgt: power(1) => on, power (0) => off */
  218:         int    (*config)(int, char*, DevConf*);   // returns nil on error
  219: };

  747: extern  Dev*     devtab[];

各デバイスごとにDevを持つわけだが,例えば,マウントデバイス(#M)は,次のような定義になっている.

port/devmnt.c
 1178: Dev mntdevtab = {
 1179:         'M',
 1180:         "mnt",
 1181: 
 1182:         mntreset,
 1183:         devinit,
 1184:         devshutdown,
 1185:         mntattach,
 1186:         mntwalk,
 1187:         mntstat,
 1188:         mntopen,
 1189:         mntcreate,
 1190:         mntclose,
 1191:         mntread,
 1192:         devbread,
 1193:         mntwrite,
 1194:         devbwrite,
 1195:         mntremove,
 1196:         mntwstat,
 1197: };