⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 00000015.htm

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -