デバイステーブル(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: };