6、用于打开的服务进程版本2
在前面的章节中,我们开发了一个用于打开文件的服务进程,这个服务进程通过客户进程使用fork和exec被运行,用这个例子展示了我们如何将一个文件描述符号从一个子进程传递给父进程。本节我们开发一个守护进程形式的打开服务进程。一个服务进程处理所有的客户进程请求,由于不用fork和exec了,所以我们期望这样的效率可能会更高。我们还是使用s-pipe在客户和服务进程之间传递文件描述符号(两个没有关系的进程)。我们将要使用前面介绍的三个函数:serv_listen,serv_accept和cli_conn。这个服务进程也展示了通过前面的select和poll函数如何处理多个客户进程。
客户端
客户进程和前面的客户进程是一样的。实际上,文件main.c是一样的。
头文件open.h,版本2
我们向open.h头文件中添加了如下的行:
#define CS_OPEN "/home/sar/opend" /* server's well-known name */
csopen函数,版本2
文件open.c相比前面的有所变化,因为我们现在使用cli_conn而不是使用fork和exec了。下面就是相关的代码:
#include "open.h"
#include <sys/uio.h> /* struct iovec */
/*
* Open the file by sending the "name" and "oflag" to the
* connection server and reading a file descriptor back.
*/
int csopen(char *name, int oflag)
{
int len;
char buf[10];
struct iovec iov[3];
static int csfd = -1;
if (csfd < 0) { /* open connection to conn server */
if ((csfd = cli_conn(CS_OPEN)) < 0)
err_sys("cli_conn error");
}
sprintf(buf, " %d", oflag); /* oflag to ascii */
iov[0].iov_base = CL_OPEN " "; /* string concatenation */
iov[0].iov_len = strlen(CL_OPEN) + 1;
iov[1].iov_base = name;
iov[1].iov_len = strlen(name);
iov[2].iov_base = buf;
iov[2].iov_len = strlen(buf) + 1; /* null always sent */
len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
if (writev(csfd, &iov[0], 3) != len)
err_sys("writev error");
/* read back descriptor; returned errors handled by write() */
return(recv_fd(csfd, write));
}
客户到服务进程之间的协议保持不变。
网友评论