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

📄 ch16_11.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD><TITLE>Recipe 16.10. Communicating Between Related Processes (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:43:53Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch16_01.htm"TITLE="16. Process Management and Communication"><LINKREL="prev"HREF="ch16_10.htm"TITLE="16.9. Controlling the Input, Output, and Error of Another Program"><LINKREL="next"HREF="ch16_12.htm"TITLE="16.11. Making a Process Look Like a File with Named Pipes"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_10.htm"TITLE="16.9. Controlling the Input, Output, and Error of Another Program"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 16.9. Controlling the Input, Output, and Error of Another Program"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch16_01.htm"TITLE="16. Process Management and Communication"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch16_12.htm"TITLE="16.11. Making a Process Look Like a File with Named Pipes"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 16.11. Making a Process Look Like a File with Named Pipes"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch16-14419">16.10. Communicating Between Related Processes</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1604">Problem<ACLASS="indexterm"NAME="ch16-idx-1000006345-0"></A><ACLASS="indexterm"NAME="ch16-idx-1000006345-1"></A><ACLASS="indexterm"NAME="ch16-idx-1000006345-2"></A></A></H3><PCLASS="para">You have two related processes that need to communicate, and you need better control than you can get from <CODECLASS="literal">open</CODE>, <CODECLASS="literal">system</CODE>, and backticks.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1610">Solution</A></H3><PCLASS="para">Use <CODECLASS="literal">pipe</CODE> and then <CODECLASS="literal">fork</CODE>:</P><PRECLASS="programlisting">pipe(READER, WRITER);if (fork) {    # run parent code, either reading or writing, not both} else {    # run child code, either reading or writing, not both}</PRE><PCLASS="para">Or use a special forking form of <CODECLASS="literal">open</CODE>:</P><PRECLASS="programlisting">if ($pid = open(CHILD, &quot;|-&quot;)) {        # run parent code, writing to child} else {    die &quot;cannot fork: $!&quot; unless defined $pid;    # otherwise run child code here, reading from parent}</PRE><PCLASS="para">Or, going the other way:</P><PRECLASS="programlisting">if ($pid = open(CHILD, &quot;-|&quot;)) {    # run parent code, reading from child} else {    die &quot;cannot fork: $!&quot; unless defined $pid;    # otherwise run child code here, writing to parent}</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch16-pgfId-1656">Discussion</A></H3><PCLASS="para">Pipes are simply two connected filehandles, where data written to one filehandle can be read by the other. The <CODECLASS="literal">pipe</CODE> function creates two filehandles linked in this way, one writable and one readable. Even though you can't take two already existing filehandles and link them, <CODECLASS="literal">pipe</CODE> can be used for communication between processes. One process creates a pair of filehandles with the <CODECLASS="literal">pipe</CODE> functions, then forks off a child, resulting in two distinct processes both running in the same program, each with a copy of the connected filehandles.</P><PCLASS="para">It doesn't matter which process is the reader and which is the writer, so long as one of them takes one role and its peer process takes the other. You can only have one-way communication. (But read on.)</P><PCLASS="para">We'll pull in the IO::Handle module so we can call its <EMCLASS="emphasis"></EM><ACLASS="indexterm"NAME="ch16-idx-1000006357-0"></A><CODECLASS="literal">autoflush()</CODE> method. (You could instead play the <CODECLASS="literal">select</CODE> games described in <ACLASS="xref"HREF="ch07_01.htm"TITLE="File Access">Chapter 7, <CITECLASS="chapter">File Access</CITE></A>, if you prefer a lightweight solution.) If we didn't, our single line of output would get lodged in the pipe and not make it through to the other side until we closed that handle.</P><PCLASS="para">The version of the parent writing to the child is shown in <ACLASS="xref"HREF="ch16_11.htm#ch16-16018"TITLE="pipe1">Example 16.3</A>.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch16-16018">Example 16.3: pipe1</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# <ACLASS="indexterm"NAME="ch16-idx-1000006351-0"></A>pipe1 - use pipe and fork so parent can send to childuse IO::Handle;pipe(READER, WRITER);WRITER-&gt;autoflush(1);if ($pid = fork) {    close READER;    print WRITER &quot;Parent Pid $$ is sending this\n&quot;;    close WRITER;    waitpid($pid,0);} else {    die &quot;cannot fork: $!&quot; unless defined $pid;    close WRITER;    chomp($line = &lt;READER&gt;);    print &quot;Child Pid $$ just read this: `$line'\n&quot;;    close READER;  # this will happen anyway    exit;}</PRE></DIV><PCLASS="para">In the examples in this recipe, most error checking has been left as an exercise for the reader. This is so you can more clearly see how the functions interact. In real life, test the return values of all system calls.</P><PCLASS="para">The version of the child writing to the parent is shown in <ACLASS="xref"HREF="ch16_11.htm#ch16-26121"TITLE="pipe2">Example 16.4</A>.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch16-26121">Example 16.4: pipe2</A></H4><PRECLASS="programlisting">#!/usr/bin/perl -w# <ACLASS="indexterm"NAME="ch16-idx-1000006352-0"></A>pipe2 - use pipe and fork so child can send to parentuse IO::Handle;pipe(READER, WRITER);WRITER-&gt;autoflush(1);if ($pid = fork) {    close WRITER;    chomp($line = &lt;READER&gt;);    print &quot;Parent Pid $$ just read this: `$line'\n&quot;;    close READER;    waitpid($pid,0);} else {    die &quot;cannot fork: $!&quot; unless defined $pid;    close READER;    print WRITER &quot;Child Pid $$ is sending this\n&quot;;    close WRITER;  # this will happen anyway    exit;}</PRE></DIV><PCLASS="para">In most code, both halves would go into loops, with the reader continuing to read until end of file. This happens when the writer closes or exits.</P><PCLASS="para">Because piped filehandles are not bidirectional, each process uses just one of the pair and closes the filehandle it doesn't use. The reason is subtle; picture the situation where the reader does not close the writable filehandle. If the writer then exits while the reader is trying to read something, the reader will hang forever. This is because the system won't tell the reader that there's no more data to be read until all copies of the writable filehandle are closed.</P><PCLASS="para">The <CODECLASS="literal">open</CODE><ACLASS="indexterm"NAME="ch16-idx-1000006358-0"></A><ACLASS="indexterm"NAME="ch16-idx-1000006358-1"></A> function, when passed as its second argument either <CODECLASS="literal">&quot;-|&quot;</CODE> or <CODECLASS="literal">&quot;|-&quot;</CODE> will implicitly pipe and fork. This makes the piping code above slightly easier. The child talks to the parent over STDIN or STDOUT, depending on whether <CODECLASS="literal">&quot;-|&quot;</CODE> or <CODECLASS="literal">&quot;|-&quot;</CODE> was used.</P><PCLASS="para">Using <CODECLASS="literal">open</CODE> this way, if the parent wants to write to the child, it does something like what's shown in <ACLASS="xref"HREF="ch16_11.htm#ch16-36681"TITLE="pipe3">Example 16.5</A>.</P><DIVCLASS="example"><H4CLASS="example"><ACLASS="title"NAME="ch16-36681">Example 16.5: pipe3</A></H4

⌨️ 快捷键说明

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