システムインタフェース

非同期でファイルを開く

アプリケーションは、遠隔ホストからマウントされたファイルシステム内や、初期化が遅れているデバイス上の通常ファイルをダイナミックに開く必要がある場合もあります。ただし、そのようなファイルを開く状態が進行している間は、アプリケーションは他のイベントへ実時間応答できなくなります。この問題は SunOS 5 では、2 番目のプロセスが実際にファイルを開き、そのファイル記述子を実時間プロセスに渡すことによって解決できます。

ファイル記述子の転送

SunOS 5 の STREAMS インタフェースは、開いているファイルの記述子をプロセスからプロセスへ渡す機構を提供しています。開いているファイルの記述子を持つプロセスは、ioctl(2) 関数にコマンド引数 I_SENDFD を付けて使用します。2 番目のプロセスは、ioctl() 関数にコマンド引数 I_RECVFD を付けて呼び出し、ファイル記述子を取得します。

例 9-1 では、親プロセスがまずテストファイルについての情報を表示し、その後パイプを作成します。次に、親プロセスは子プロセスを作成し、子プロセスはテストファイルを開いて、そのファイル記述子をパイプを通じて親に戻します。親プロセスは、新しいファイル記述子についての状態情報を表示します。


例 9-1 ファイル記述子の転送

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <stdio.h>

#define TESTFILE "/dev/null"
main(int argc, char *argv[])
{
	int fd;
	int pipefd[2];
	struct stat statbuf;

	stat(TESTFILE, &statbuf);
	statout(TESTFILE, &statbuf);
	pipe(pipefd);
	if (fork() == 0) {
		close(pipefd[0]);
		sendfd(pipefd[1]);
	} else {
		close(pipefd[1])
		recvfd(pipefd[0]);
	}
}

sendfd(int p)
{
	int tfd;

	tfd = open(TESTFILE, O_RDWR);
	ioctl(p, I_SENDFD, tfd);
}

recvfd(int p)
{
	struct strrecvfd rfdbuf;
	struct stat statbuf;
	char			fdbuf[32];

	ioctl(p, I_RECVFD, &rfdbuf);
	fstat(rfdbuf.fd, &statbuf);
	sprintf(fdbuf, "recvfd=%d", rfdbuf.fd);
	statout(fdbuf, &statbuf);	
}

statout(char *f, struct stat *s)
{
	printf("stat: from=%s mode=0%o, ino=%ld, dev=%lx, rdev=%lx¥n",
		f, s->st_mode, s->st_ino, s->st_dev, s->st_rdev);
	fflush(stdout);
}