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

📄 00000015.htm

📁 一份很好的linux入门资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
&nbsp;&nbsp;&nbsp;close(fd[0]);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;if&nbsp;(fd[1]&nbsp;!=&nbsp;STDIN_FILENO)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(dup2(fd[1],&nbsp;STDIN_FILENO)&nbsp;!=&nbsp;STDIN_FILENO)&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(&quot;dup2&nbsp;error&nbsp;to&nbsp;stdin&quot;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;if&nbsp;(fd[1]&nbsp;!=&nbsp;STDOUT_FILENO)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(dup2(fd[1],&nbsp;STDOUT_FILENO)&nbsp;!=&nbsp;STDOUT_FILENO)&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(&quot;dup2&nbsp;error&nbsp;to&nbsp;stdout&quot;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;if&nbsp;(execl(&quot;./opend&quot;,&nbsp;&quot;opend&quot;,&nbsp;NULL)&nbsp;&lt;&nbsp;0)&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;err_sys(&quot;execl&nbsp;error&quot;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;close(fd[1]);&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;parent&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;sprintf(buf,&nbsp;&quot;&nbsp;%d&quot;,&nbsp;oflag);&nbsp;&nbsp;/*&nbsp;oflag&nbsp;to&nbsp;ascii&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;iov[0].iov_base&nbsp;=&nbsp;CL_OPEN&nbsp;&quot;&nbsp;&quot;;&nbsp;&nbsp;<BR>&nbsp;iov[0].iov_len&nbsp;&nbsp;=&nbsp;strlen(CL_OPEN)&nbsp;+&nbsp;1;&nbsp;&nbsp;<BR>&nbsp;iov[1].iov_base&nbsp;=&nbsp;name;&nbsp;&nbsp;<BR>&nbsp;iov[1].iov_len&nbsp;&nbsp;=&nbsp;strlen(name);&nbsp;&nbsp;<BR>&nbsp;iov[2].iov_base&nbsp;=&nbsp;buf;&nbsp;&nbsp;<BR>&nbsp;iov[2].iov_len&nbsp;&nbsp;=&nbsp;strlen(buf)&nbsp;+&nbsp;1;&nbsp;/*&nbsp;+1&nbsp;for&nbsp;null&nbsp;at&nbsp;end&nbsp;of&nbsp;buf&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;len&nbsp;=&nbsp;iov[0].iov_len&nbsp;+&nbsp;iov[1].iov_len&nbsp;+&nbsp;iov[2].iov_len;&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(writev(fd[0],&nbsp;&amp;iov[0],&nbsp;3)&nbsp;!=&nbsp;len)&nbsp;&nbsp;<BR>&nbsp;&nbsp;err_sys(&quot;writev&nbsp;error&quot;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;read&nbsp;descriptor,&nbsp;returned&nbsp;errors&nbsp;handled&nbsp;by&nbsp;write()&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;return(&nbsp;recv_fd(fd[0],&nbsp;write)&nbsp;);&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;程序15.13&nbsp;&nbsp;&nbsp;csopen函数&nbsp;&nbsp;<BR>子进程关闭管道的一端,父进程关闭另一端。子进程也为它所执行的服务器将管道&nbsp;&nbsp;<BR>它使用的一端复制到其标准输入和标准输出0(另一种可选择的方案是将描述符fd&nbsp;&nbsp;<BR>[1]的ASCII&nbsp;表示形式作为一个参数传送给服务器。)&nbsp;&nbsp;<BR>父进程将请求发送给服务器,请求中包含路径名和打开方式。最后,父进程调用r&nbsp;&nbsp;<BR>ecv-fd以返回描述符或错误消息。如若服务器返回一错误消息则调用write,向标&nbsp;&nbsp;<BR>准出错输出该消息。&nbsp;&nbsp;<BR>现在,观察open服务器。其程序是opend,它由子进程执行(见程序15.13)。先观&nbsp;&nbsp;<BR>察opend.h头文件(程序15.14),它包括了系统头文件,并且说明了全局变量和函&nbsp;&nbsp;<BR>数原型。&nbsp;&nbsp;<BR>#include&nbsp;&lt;sys/types.h&gt;&nbsp;&nbsp;<BR>#include&nbsp;&lt;errno.h&gt;&nbsp;&nbsp;<BR>#include&nbsp;&quot;ourhdr.h&quot;&nbsp;&nbsp;<BR>#define&nbsp;CL_OPEN&nbsp;&quot;open&quot;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;client's&nbsp;request&nbsp;for&nbsp;server&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;declare&nbsp;global&nbsp;variables&nbsp;*/&nbsp;&nbsp;<BR>extern&nbsp;char&nbsp;&nbsp;errmsg[];&nbsp;/*&nbsp;error&nbsp;message&nbsp;string&nbsp;to&nbsp;return&nbsp;to&nbsp;client&nbsp;*/&nbsp;&nbsp;<BR>extern&nbsp;int&nbsp;&nbsp;oflag;&nbsp;&nbsp;/*&nbsp;open()&nbsp;flag:&nbsp;O_xxx&nbsp;...&nbsp;*/&nbsp;&nbsp;<BR>extern&nbsp;char&nbsp;*pathname;&nbsp;/*&nbsp;of&nbsp;file&nbsp;to&nbsp;open()&nbsp;for&nbsp;client&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;function&nbsp;prototypes&nbsp;*/&nbsp;&nbsp;<BR>int&nbsp;&nbsp;&nbsp;cli_args(int,&nbsp;char&nbsp;**);&nbsp;&nbsp;<BR>void&nbsp;&nbsp;request(char&nbsp;*,&nbsp;int,&nbsp;int);&nbsp;&nbsp;<BR>程序.15.14 opend.h头文件&nbsp;&nbsp;<BR>#include&nbsp;&quot;opend.h&quot;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;define&nbsp;global&nbsp;variables&nbsp;*/&nbsp;&nbsp;<BR>char&nbsp;&nbsp;errmsg[MAXLINE];&nbsp;&nbsp;<BR>int&nbsp;&nbsp;&nbsp;oflag;&nbsp;&nbsp;<BR>char&nbsp;*pathname;&nbsp;&nbsp;<BR>int&nbsp;&nbsp;<BR>main(void)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;int&nbsp;&nbsp;nread;&nbsp;&nbsp;<BR>&nbsp;char&nbsp;buf[MAXLINE];&nbsp;&nbsp;<BR>&nbsp;for&nbsp;(&nbsp;;&nbsp;;&nbsp;)&nbsp;{&nbsp;/*&nbsp;read&nbsp;arg&nbsp;buffer&nbsp;from&nbsp;client,&nbsp;process&nbsp;request&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;&nbsp;if&nbsp;(&nbsp;(nread&nbsp;=&nbsp;read(STDIN_FILENO,&nbsp;buf,&nbsp;MAXLINE))&nbsp;&lt;&nbsp;0)&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;err_sys(&quot;read&nbsp;error&nbsp;on&nbsp;stream&nbsp;pipe&quot;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;else&nbsp;if&nbsp;(nread&nbsp;==&nbsp;0)&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;/*&nbsp;client&nbsp;has&nbsp;closed&nbsp;the&nbsp;stream&nbsp;pipe&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;&nbsp;request(buf,&nbsp;nread,&nbsp;STDIN_FILENO);&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;exit(0);&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>程序15.15 main函数&nbsp;&nbsp;<BR>#include&nbsp;&quot;opend.h&quot;&nbsp;&nbsp;<BR>#include&nbsp;&lt;fcntl.h&gt;&nbsp;&nbsp;<BR>void&nbsp;&nbsp;<BR>request(char&nbsp;*buf,&nbsp;int&nbsp;nread,&nbsp;int&nbsp;fd)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;int&nbsp;&nbsp;newfd;&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(buf[nread-1]&nbsp;!=&nbsp;0)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;sprintf(errmsg,&nbsp;&quot;request&nbsp;not&nbsp;null&nbsp;terminated:&nbsp;%*.*s\n&quot;,&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nread,&nbsp;nread,&nbsp;buf);&nbsp;&nbsp;<BR>&nbsp;&nbsp;send_err(STDOUT_FILENO,&nbsp;-1,&nbsp;errmsg);&nbsp;&nbsp;<BR>&nbsp;&nbsp;return;&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;parse&nbsp;the&nbsp;arguments,&nbsp;set&nbsp;options&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(buf_args(buf,&nbsp;cli_args)&nbsp;&lt;&nbsp;0)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;send_err(STDOUT_FILENO,&nbsp;-1,&nbsp;errmsg);&nbsp;&nbsp;<BR>&nbsp;&nbsp;return;&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(&nbsp;(newfd&nbsp;=&nbsp;open(pathname,&nbsp;oflag))&nbsp;&lt;&nbsp;0)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;sprintf(errmsg,&nbsp;&quot;can't&nbsp;open&nbsp;%s:&nbsp;%s\n&quot;,&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pathname,&nbsp;strerror(errno));&nbsp;&nbsp;<BR>&nbsp;&nbsp;send_err(STDOUT_FILENO,&nbsp;-1,&nbsp;errmsg);&nbsp;&nbsp;<BR>&nbsp;&nbsp;return;&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;send&nbsp;the&nbsp;descriptor&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(send_fd(STDOUT_FILENO,&nbsp;newfd)&nbsp;&lt;&nbsp;0)&nbsp;&nbsp;<BR>&nbsp;&nbsp;err_sys(&quot;send_fd&nbsp;error&quot;);&nbsp;&nbsp;<BR>&nbsp;close(newfd);&nbsp;&nbsp;/*&nbsp;we're&nbsp;done&nbsp;with&nbsp;descriptor&nbsp;*/&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>程序15.16&nbsp;&nbsp;request函数&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;主函数(程序15.15)经流管道(它的标准输入)读来自客户的请求,然后调&nbsp;&nbsp;<BR>用函数request。&nbsp;&nbsp;<BR>程序15.16中的request&nbsp;函数承担全部工作。它调用函数buf_args将客户请求分解&nbsp;&nbsp;<BR>成标准argv型的参数表,然后调用函数cli_args以处理客户的参数。如若一切正常&nbsp;&nbsp;<BR>,则调用open&nbsp;以打开相应文件,接着调用send_fd,经由流管道(它的标准输出)&nbsp;&nbsp;<BR>将描述符回送给客户。如若出错则调用send_err回送一则出错消息,其中使用我们&nbsp;&nbsp;<BR>在前面说明了的客户/服务器协议。&nbsp;&nbsp;<BR>#include&nbsp;&quot;ourhdr.h&quot;&nbsp;&nbsp;<BR>#define&nbsp;MAXARGC&nbsp;&nbsp;50&nbsp;/*&nbsp;max&nbsp;number&nbsp;of&nbsp;arguments&nbsp;in&nbsp;buf&nbsp;*/&nbsp;&nbsp;<BR>#define&nbsp;WHITE&nbsp;&quot;&nbsp;\t\n&quot;&nbsp;/*&nbsp;white&nbsp;space&nbsp;for&nbsp;tokenizing&nbsp;arguments&nbsp;*/&nbsp;&nbsp;<BR>/*&nbsp;buf[]&nbsp;contains&nbsp;white-space&nbsp;separated&nbsp;arguments.&nbsp;&nbsp;We&nbsp;convert&nbsp;it&nbsp;&nbsp;<BR>&nbsp;*&nbsp;to&nbsp;an&nbsp;argv[]&nbsp;style&nbsp;array&nbsp;of&nbsp;pointers,&nbsp;and&nbsp;call&nbsp;the&nbsp;user's&nbsp;&nbsp;<BR>&nbsp;*&nbsp;function&nbsp;(*optfunc)()&nbsp;to&nbsp;process&nbsp;the&nbsp;argv[]&nbsp;array.&nbsp;&nbsp;<BR>&nbsp;*&nbsp;We&nbsp;return&nbsp;-1&nbsp;to&nbsp;the&nbsp;caller&nbsp;if&nbsp;there's&nbsp;a&nbsp;problem&nbsp;parsing&nbsp;buf,&nbsp;&nbsp;<BR>&nbsp;*&nbsp;else&nbsp;we&nbsp;return&nbsp;whatever&nbsp;optfunc()&nbsp;returns.&nbsp;&nbsp;Note&nbsp;that&nbsp;user's&nbsp;&nbsp;<BR>&nbsp;*&nbsp;buf[]&nbsp;array&nbsp;is&nbsp;modified&nbsp;(nulls&nbsp;placed&nbsp;after&nbsp;each&nbsp;token).&nbsp;*/&nbsp;&nbsp;<BR>int&nbsp;&nbsp;<BR>buf_args(char&nbsp;*buf,&nbsp;int&nbsp;(*optfunc)(int,&nbsp;char&nbsp;**))&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;char&nbsp;*ptr,&nbsp;*argv[MAXARGC];&nbsp;&nbsp;<BR>&nbsp;int&nbsp;&nbsp;argc;&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(strtok(buf,&nbsp;WHITE)&nbsp;==&nbsp;NULL)&nbsp;&nbsp;/*&nbsp;an&nbsp;argv[0]&nbsp;is&nbsp;required&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;&nbsp;return(-1);&nbsp;&nbsp;<BR>&nbsp;argv[argc&nbsp;=&nbsp;0]&nbsp;=&nbsp;buf;&nbsp;&nbsp;<BR>&nbsp;while&nbsp;(&nbsp;(ptr&nbsp;=&nbsp;strtok(NULL,&nbsp;WHITE))&nbsp;!=&nbsp;NULL)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;if&nbsp;(++argc&nbsp;&gt;=&nbsp;MAXARGC-1)&nbsp;/*&nbsp;-1&nbsp;for&nbsp;room&nbsp;for&nbsp;NULL&nbsp;at&nbsp;end&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;return(-1);&nbsp;&nbsp;<BR>&nbsp;&nbsp;argv[argc]&nbsp;=&nbsp;ptr;&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;argv[++argc]&nbsp;=&nbsp;NULL;&nbsp;&nbsp;<BR>&nbsp;return(&nbsp;(*optfunc)(argc,&nbsp;argv)&nbsp;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;/*&nbsp;Since&nbsp;argv[]&nbsp;pointers&nbsp;point&nbsp;into&nbsp;the&nbsp;user's&nbsp;buf[],&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user's&nbsp;function&nbsp;can&nbsp;just&nbsp;copy&nbsp;the&nbsp;pointers,&nbsp;even&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;though&nbsp;argv[]&nbsp;array&nbsp;will&nbsp;disappear&nbsp;on&nbsp;return.&nbsp;*/&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>程序15.17 buf_args函数&nbsp;&nbsp;<BR>  buf_args调用的服务器函数是cli_args(程序15.18)。它验证客户发送的参&nbsp;&nbsp;<BR>数数是否正确,然后将路径名和打开方式存放在全局变量中。&nbsp;&nbsp;<BR>  这样也就完成了open服务器,它由客户执行fork和exec而调用。在fork之前创&nbsp;&nbsp;<BR>建了一个流管道,然后客户和服务器用其进行通信。在这种安排下,每个客户都有&nbsp;&nbsp;<BR>一服务器。&nbsp;&nbsp;<BR>在下一节观察了客户一服务器连接后,我们将在15.6节重新实现一个open服务器,&nbsp;&nbsp;<BR>其中用一个精灵进程作为服务器,所有客户都与其进行联系。&nbsp;&nbsp;<BR>#include&nbsp;&quot;opend.h&quot;&nbsp;&nbsp;<BR>/*&nbsp;This&nbsp;function&nbsp;is&nbsp;called&nbsp;by&nbsp;buf_args(),&nbsp;which&nbsp;is&nbsp;called&nbsp;by&nbsp;&nbsp;<BR>&nbsp;*&nbsp;request().&nbsp;&nbsp;buf_args()&nbsp;has&nbsp;broken&nbsp;up&nbsp;the&nbsp;client's&nbsp;buffer&nbsp;&nbsp;<BR>&nbsp;*&nbsp;into&nbsp;an&nbsp;argv[]&nbsp;style&nbsp;array,&nbsp;which&nbsp;we&nbsp;now&nbsp;process.&nbsp;*/&nbsp;&nbsp;<BR>int&nbsp;&nbsp;<BR>cli_args(int&nbsp;argc,&nbsp;char&nbsp;**argv)&nbsp;&nbsp;<BR>{&nbsp;&nbsp;<BR>&nbsp;if&nbsp;(argc&nbsp;!=&nbsp;3&nbsp;||&nbsp;strcmp(argv[0],&nbsp;CL_OPEN)&nbsp;!=&nbsp;0)&nbsp;{&nbsp;&nbsp;<BR>&nbsp;&nbsp;strcpy(errmsg,&nbsp;&quot;usage:&nbsp;&lt;pathname&gt;&nbsp;&lt;oflag&gt;\n&quot;);&nbsp;&nbsp;<BR>&nbsp;&nbsp;return(-1);&nbsp;&nbsp;<BR>&nbsp;}&nbsp;&nbsp;<BR>&nbsp;pathname&nbsp;=&nbsp;argv[1];&nbsp;&nbsp;/*&nbsp;save&nbsp;ptr&nbsp;to&nbsp;pathname&nbsp;to&nbsp;open&nbsp;*/&nbsp;&nbsp;<BR>&nbsp;oflag&nbsp;=&nbsp;atoi(argv[2]);&nbsp;&nbsp;<BR>&nbsp;return(0);&nbsp;&nbsp;<BR>}&nbsp;&nbsp;<BR>程序15.18&nbsp;&nbsp;cli_args函数&nbsp;&nbsp;<BR>15.5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;客户-服务器连接函数&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对于相关进程(例如,父进程和子进程)之间的IPC,流管道是非常有用的。&nbsp;&nbsp;<BR>前节所述的open服务器使用末命名的流管道能从子进程向父进程传送文件描述符。&nbsp;&nbsp;<BR>但是当我们处理无关进程时(例如,若服务器是一精灵进程),则需要使用有名的&nbsp;&nbsp;<BR>流管道。&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们可以先构造一末名流管道(用s_pipe&nbsp;函数),然后对每一端加上一

⌨️ 快捷键说明

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