📄 00000015.htm
字号:
送errmsg和status字节。status的值应在-1至-225之间 <BR>客户调用secv_fd接收一描述符。如果一切正常(发送者调用了send_fd),则作为函 <BR>数值返回非负描述符。否则,返回值是由send_err发送的status(在-1和-255之间的 <BR>一个负值)。另外,如果服务器发送了一条出错消息,则客户调用它自己的userfunc <BR>处理该消息。userfunc的第一个参数是常数STDERR_FILENO, 然后是指向出错消息 <BR>的指针及其长度。客户常将userfunc指定为UNIX的Write函数。 <BR>我们实现了用于这三个函数的我们自己制定的协议。为发送一描述符,send_fd先发 <BR>送两个0字节,然后是实际描述符。为了发送一条出错消息,send_err 发送errmsg, <BR>然后是1个0字节,最后是status字节的绝对值(1-255)。recv_fd读流管道中所有字 <BR>节直至null字符。在null字符之前的所有字符都送给调用者的userfunc。recv_fd <BR>读到的下一个字节是status字节.若status字节为0,那么一个描述符已传送,否 <BR>则表示没有接收到描述符. <BR>Send_err函数在将出错消息写到流管道后,即调用send_fg函数.这示于程序15 <BR>.4中。 <BR>#include "ourhdr.h" <BR>/* Used when we had planned to send an fd using send_fd(), <BR> * but encountered an error instead. We send the error back <BR> * using the send_fd()/recv_fd() protocol. */ <BR>int <BR>send_err(int clifd, int errcode, const char *msg) <BR>{ <BR> int n; <BR> if ( (n = strlen(msg)) > 0) <BR> if (writen(clifd, msg, n) != n) /* send the error message */ <BR> return(-1); <BR> if (errcode >= 0) <BR> errcode = -1; /* must be negative */ <BR> if (send_fd(clifd, errcode) < 0) <BR> return(-1); <BR> return(0); <BR>} <BR>程序15.4 send_err函数 <BR>15.3.1 SVR4 <BR>在SVR4之下,文件描述符用两条ioctl命令在一流管道中交换,这两条命令是:I_ <BR>SENDFD 和I_RECVFD。为了发送一描述符,我们将ioctl的第三个参数设置为实际描 <BR>述符。这示于程序15.5中。 <BR>#include <sys/types.h> <BR>#include <stropts.h> <BR>#include "ourhdr.h" <BR>/* Pass a file descriptor to another process. <BR> * If fd<0, then -fd is sent back instead as the error status. */ <BR>int <BR>send_fd(int clifd, int fd) <BR>{ <BR> char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */ <BR> buf[0] = 0; /* null byte flag to recv_fd() */ <BR> if (fd < 0) { <BR> buf[1] = -fd; /* nonzero status means error */ <BR> if (buf[1] == 0) <BR> buf[1] = 1; /* -256, etc. would screw up protocol */ <BR> } else { <BR> buf[1] = 0; /* zero status means OK */ <BR> } <BR> if (write(clifd, buf, 2) != 2) <BR> return(-1); <BR> if (fd >= 0) <BR> if (ioctl(clifd, I_SENDFD, fd) < 0) <BR> return(-1); <BR> return(0); <BR>} <BR>程序15.5 SVR4下的send_fd函数 <BR>当接收一描述符时,ioctl的第三个参数是一指向strrecvfd结构的指针。 <BR>_______________________________________________________________________ <BR>______ <BR>struct strrecvfd { <BR> int fd; 新描述符 <BR> uid_t uid; 发送者的有效用户ID <BR> gid_t gid; 发送者的有效组ID <BR> char fill[8]; <BR>} <BR>_______________________________________________________________________ <BR>______ <BR>recv_fd读流管道直到接收到双字节协议的第一个字节(null字节).当发出带I_ <BR>RECVFD命令的ioctl时,在流读首处的第一条消息应当是一个描述符,它是由I_SE <BR>NDFD发来的,或者得到一条出错消息。这示于程序15.6中。 <BR>#include <sys/types.h> <BR>#include <stropts.h> <BR>#include "ourhdr.h" <BR>/* Receive a file descriptor from another process (a server). <BR> * In addition, any data received from the server is passed <BR> * to (*userfunc)(STDERR_FILENO, buf, nbytes). We have a <BR> * 2-byte protocol for receiving the fd from send_fd(). */ <BR>int <BR>recv_fd(int servfd, ssize_t (*userfunc)(int, const void *, size_t)) <BR>{ <BR> int newfd, nread, flag, status; <BR> char *ptr, buf[MAXLINE]; <BR> struct strbuf dat; <BR> struct strrecvfd recvfd; <BR> status = -1; <BR> for ( ; ; ) { <BR> dat.buf = buf; <BR> dat.maxlen = MAXLINE; <BR> flag = 0; <BR> if (getmsg(servfd, NULL, &dat, &flag) < 0) <BR> err_sys("getmsg error"); <BR> nread = dat.len; <BR> if (nread == 0) { <BR> err_ret("connection closed by server"); <BR> return(-1); <BR> } <BR> /* See if this is the final data with null & status. <BR> Null must be next to last byte of buffer, status <BR> byte is last byte. Zero status means there must <BR> be a file descriptor to receive. */ <BR> for (ptr = buf; ptr < &buf[nread]; ) { <BR> if (*ptr++ == 0) { <BR> if (ptr != &buf[nread-1]) <BR> err_dump("message format error"); <BR> status = *ptr & 255; <BR> if (status == 0) { <BR> if (ioctl(servfd, I_RECVFD, &recvfd) < 0) <BR> return(-1); <BR> newfd = recvfd.fd; /* new descriptor */ <BR> } else <BR> newfd = -status; <BR> nread -= 2; <BR> } <BR> } <BR> if (nread > 0) <BR> if ((*userfunc)(STDERR_FILENO, buf, nread) != nread) <BR> return(-1); <BR> if (status >= 0) /* final data has arrived */ <BR> return(newfd); /* descriptor, or -status */ <BR> } <BR>} <BR>程序15.6 SVR4下的recv_fd函数 <BR>15.3.2 4.3BSD <BR> 不幸,对于4.3BSD以及在其基础上构造的SunOS和Ultrix,以及从4.3BSD <BR>Reno开始的后续版本我们必须提供不同的实现。 <BR>为了交换文件描述符,调用sendmsg(2)和recvmsg(2)函数。这两个函数的参数中都 <BR>有一个指向msghdr的指针,该结构包含了所有关于要发送和接收消息的信息。该结 <BR>构定义在〈sys/socket.h〉 头文件中,在BSD4.3之下,其样式是: <BR>_______________________________________________________________________ <BR>______ <BR>strcut msghdr { <BR> caddr_t msg_name; 可选的地址 <BR> int msg_namelen; 地址长度 <BR> struct iovec msg_iov; 散布/聚集数组 <BR> int msg_iovlen; 在msg_iov数组中的元素数 <BR> caddr_t msg_accrights; 存取权发送/接收到 <BR> int msg-accrightslen; 存取权缓存的长度 <BR>} <BR>_______________________________________________________________________ <BR>______ <BR>头两个元素通常用于在网络连接上发送数据报文,在这里,目的地址可以由每个数 <BR>据报文指定。下面两个元素使我们可以指定缓存的数组(散布读和聚集写),这如 <BR>同我们对readv和writev函数(12.7节)的说明一样。最后两个元素处理存取权的 <BR>传送和接收。当前唯一定义的存取权是文件描述符。存取权仅可跨越一个UNIX域套 <BR>接口传送(亦即,在4.3BSD之下作为流管道我们所使用的)。为了发送或接收一文 <BR>件描述符,将msg_accrights设置为指向该整型描述符,将msg_accrightslen设置 <BR>为描述符的长度(亦即,整型的长度)。仅当此长度非0时,才传送或接收描述符 <BR>。 <BR>程序15.7是4.3BSD下的send_fd函数 <BR>#include <sys/types.h> <BR>#include <sys/socket.h> /* struct msghdr */ <BR>#include <sys/uio.h> /* struct iovec */ <BR>#include <errno.h> <BR>#include <stddef.h> <BR>#include "ourhdr.h" <BR>/* Pass a file descriptor to another process. <BR> * If fd<0, then -fd is sent back instead as the error status. */ <BR>int <BR>send_fd(int clifd, int fd) <BR>{ <BR> struct iovec iov[1]; <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -