有时,可能要求应用程序动态打开从远程主机挂载的文件系统中的常规文件,或者其初始化可能延迟的设备上的常规文件。但是,正在处理此类打开文件的请求的同时,应用程序不能实现对其他事件的实时响应。SunOS 软件通过以下方法解决了此问题:让另一个进程处理文件的实际打开操作,然后将文件描述符传递到实时进程。
SunOS 平台提供的 STREAMS 接口提供了一种将打开的文件描述符从一个进程传递到另一个进程的机制。带有打开文件描述符的进程使用带有 I_SENDFD 命令参数的 ioctl(2)。另一个进程通过调用带有 I_RECVFD 命令参数的 ioctl(2) 来获取该文件描述符。
在以下示例中,父进程输出有关测试文件的信息,并创建一个管道。然后,父进程会创建一个子进程,该子进程可打开该测试文件并通过管道将打开的文件描述符传递回父进程。随后父进程会显示关于新文件描述符的状态信息。
#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); }