srvデバイス

また,日が開いてしまった.なかなか毎日更新するのは難しいなぁ.

UNIXで名前付きパイプ(またの名をFIFOスペシャルファイル)を作る場合は,専用のライブラリ関数mkfifo(3)を使う必要があるが,Plan9では,srvバイス(#s)を使って実現できる.man srv(3)の例を次に引用する.

int fd, p[2];
char buf[32];
pipe(p);
fd = create("/srv/namedpipe", OWRITE, 0666);
fprint(fd, "%d", p[0]);
close(fd);
close(p[0]);
fprint(p[1], "hello");

パイプを生成し,入力側のファイル記述子を/srv/namedpipeに書き込んでいる.これで,/srv/namedpipeへの読書きが,このパイプを介してやりとりできる.例えば,あるプロセスが/srv/namedpipeを読み出すと,"hello"と返される.

話をrioに戻して,前回書いたようなファイルツリーを作っている部分を見ていこう.今までとは違い,カーネルではなく,ユーザランドソースコードであることに注意.
filsysinit関数がファイルシステム回りの初期化部分で,post関数は上のman srv(3)で示した例のように,srvバイスにパイプのファイル記述子を書き込む関数である.

cmd/rio/fsys.c
   90: post(char *name, char *envname, int srvfd)
   91: {
   92:         int fd;
   93:         char buf[32];
   94: 
   95:         fd = create(name, OWRITE|ORCLOSE|OCEXEC, 0600);
   96:         if(fd < 0)
   97:                 error(name);
   98:         sprint(buf, "%d",srvfd);
   99:         if(write(fd, buf, strlen(buf)) != strlen(buf))
  100:                 error("srv write");
  101:         putenv(envname, name);
  102: }

  122: Filsys*
  123: filsysinit(Channel *cxfidalloc)
  124: {

  126:         Filsys *fs;

  130:         fs = emalloc(sizeof(Filsys));
  131:         if(cexecpipe(&fs->cfd, &fs->sfd) < 0)
  132:                 goto Rescue;

  169:         sprint(srvpipe, "/srv/rio.%s.%d", fs->user, pid);
  170:         post(srvpipe, "wsys", fs->cfd);

postの最後に環境変数を設定しているが,今回はwsysが設定される.例えば,nsの結果で見たように,次のような結果になる.

term% echo $wsys
/srv/rio.oraccha.23

postで使われるパイプはcexepipe関数で作られる.ここでは,pipe(2)を使わず,わざわざパイプデバイス(#|)を使って,パイプをオープンしている.その理由は明日に続く.瑣末なところで,OCEXECというオープンモードは見慣れないが,exec(2)が実行されたら,ファイルをクローズするという意味である.

  108: int
  109: cexecpipe(int *p0, int *p1)
  110: {
  111:         /* pipe the hard way to get close on exec */
  112:         if(bind("#|", "/mnt/temp", MREPL) < 0)
  113:                 return -1;
  114:         *p0 = open("/mnt/temp/data", ORDWR);
  115:         *p1 = open("/mnt/temp/data1", ORDWR|OCEXEC);
  116:         unmount(nil, "/mnt/temp");
  117:         if(*p0<0 || *p1<0)
  118:                 return -1;
  119:         return 0;
  120: }

なお,Plan9のパイプについては,有澤氏の文書が詳しい.