📄 ch16_01.htm
字号:
<html><head><title>Interprocess Communication (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Interprocess Communication"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch15_03.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="part3.htm">Part 3: Perl as Technology</a></td><td align="right" valign="top" width="172"><a href="ch16_02.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h1 class="chapter">Chapter 16. Interprocess Communication</h1><div class="htmltoc"><h4 class="tochead">Contents:</h4><p><a href="ch16_01.htm">Signals</a><br><a href="ch16_02.htm">Files</a><br><a href="ch16_03.htm">Pipes</a><br><a href="ch16_04.htm">System V IPC</a><br><a href="ch16_05.htm">Sockets</a><br></p></div><p><a name="INDEX-2872"></a><a name="INDEX-2873"></a><a name="INDEX-2874"></a>Computer processes have almost as many ways of communicating as peopledo. The difficulties of interprocess communication should not beunderestimated. It doesn't do you any good to listen for verbal cueswhen your friend is using only body language. Likewise, two processescan communicate only when they agree on the means of communication, andon the conventions built on top of that. As with any kind ofcommunication, the conventions to be agreed upon range from lexical topragmatic: everything from which lingo you'll use, up to whose turn itis to talk. These conventions are necessary because it's very difficultto communicate bare semantics in the absence of context.</p><p>In our lingo, interprocess communication is usually pronounced IPC.The IPC facilities of Perl range from the very simple to the verycomplex. Which facility you should use depends on the complexity ofthe information to be communicated. The simplest kind of informationis almost no information at all: just the awareness that aparticular event has happened at a particular point in time. In Perl,these events are communicated via a signal mechanism modeled on theUnix signal system.<a name="INDEX-2875"></a></p><p><a name="INDEX-2876"></a>At the other extreme, the socket facilities of Perl allow you tocommunicate with any other process on the Internet using any mutuallysupported protocol you like. Naturally, this freedom comes at a price:you have to go through a number of steps to set up the connections andmake sure you're talking the same language as the process on the otherend. This may in turn require you to adhere to any number of otherstrange customs, depending on local conventions. To beprotocoligorically correct, you might even be required to speak alanguage like XML, or Java, or Perl. Horrors.<a name="INDEX-2877"></a></p><p><a name="INDEX-2878"></a>Sandwiched in between are some facilities intended primarily forcommunicating with processes on the same machine. These include goodold-fashioned files, pipes, FIFOs, and the various System V IPCsyscalls. Support for these facilities varies across platforms;modern Unix systems (including Apple's Mac OS X) should support all ofthem, and, except for signals and SysV IPC, most of the rest aresupported on any recent Microsoft operating systems, including pipes,forking, file locking, and sockets.<a href="#FOOTNOTE-1">[1]</a><a name="INDEX-2879"></a><a name="INDEX-2880"></a></p><blockquote class="footnote"><a name="FOOTNOTE-1"></a><p>[1] Well, except for<tt class="literal">AF_UNIX</tt> sockets.</p></blockquote><p><a name="INDEX-2881"></a><a name="INDEX-2882"></a><a name="INDEX-2883"></a><a name="INDEX-2884"></a><a name="INDEX-2885"></a>More information about porting in general can be found in the standardPerl documentation set (in whatever format your system displays it)under <em class="emphasis">perlport</em>. Microsoft-specific informationcan be found under <em class="emphasis">perlwin32</em> and<em class="emphasis">perlfork</em>, which are installed even onnon-Microsoft systems. For textbooks, we suggest thefollowing:</p><ul><li><p>The <em class="citetitle">Perl Cookbook</em>, by Tom Christiansen and NathanTorkington (O'Reilly and Associates, 1998), chapters 16 through 18.</p></li><li><p><em class="emphasis">Advanced Programming inthe UNIX Environment</em>, by W. Richard Stevens(Addison-Wesley, 1992).</p></li><li><p><em class="emphasis">TCP/IP Illustrated</em>, by W. Richard Stevens, VolumesI-III (Addison-Wesley, 1992-1996).</p></li></ul><p></p><h2 class="sect1">16.1. Signals</h2><p><a name="INDEX-2886"></a><a name="INDEX-2887"></a><a name="INDEX-2888"></a><a name="INDEX-2889"></a><a name="INDEX-2890"></a><a name="INDEX-2891"></a>Perl uses a simple signal-handling model: the <tt class="literal">%SIG</tt>hash contains references (either symbolic or hard) to user-definedsignal handlers. Certain events cause the operating system to delivera signal to the affected process. The handler corresponding to thatevent is called with one argument containing the name of the signalthat triggered it. To send a signal to another process, you use the<tt class="literal">kill</tt> function. Think of it as sending a one-bitpiece of information to the other process.<a href="#FOOTNOTE-2">[2]</a> If that process has installed a signal handler forthat signal, it can execute code when it receives the signal. Butthere's no way for the sending process to get any sort of returnvalue, other than knowing that the signal was legally sent. Thesender receives no feedback saying what, if anything, the receivingprocess did with the signal.</p><blockquote class="footnote"><a name="FOOTNOTE-2"></a><p>[2] Actually,it's more like five or six bits, depending on how many signals your OSdefines and on whether the other process makes use of the fact thatyou <em class="emphasis">didn't</em> send a different signal.</p></blockquote><p><a name="INDEX-2892"></a><a name="INDEX-2893"></a><a name="INDEX-2894"></a><a name="INDEX-2895"></a>We've classified this facility as a form of IPC, but in fact, signalscan come from various sources, not just other processes. A signalmight also come from your own process, or it might be generatedwhen the user at the keyboard types a particular sequence likeControl-C or Control-Z, or it might be manufactured by the kernel whena special event transpires, such as when a child process exits,or when your process runs out of stack space or hitsa file size or memory limit. But your own process can't easilydistinguish among these cases. A signal is like a package thatarrives mysteriously on your doorstep with no return address. You'dbest open it carefully.</p><p><a name="INDEX-2896"></a><a name="INDEX-2897"></a><a name="INDEX-2898"></a>Since entries in the <tt class="literal">%SIG</tt> array can be hard references, it'scommon practice to use anonymous functions for simple signal handlers:<blockquote><pre class="programlisting">$SIG{INT} = sub { die "\nOutta here!\n" };$SIG{ALRM} = sub { die "Your alarm clock went off" };</pre></blockquote><a name="INDEX-2899"></a><a name="INDEX-2900"></a><a name="INDEX-2901"></a><a name="INDEX-2902"></a>Or you could create a named function and assign its name or referenceto the appropriate slot in the hash. For example, to interceptinterrupt and quit signals (often bound to Control-C and Control-\ onyour keyboard), set up a handler like this:<blockquote><pre class="programlisting">sub catch_zap { my $signame = shift; our $shucks++; die "Somebody sent me a SIG$signame!";} $shucks = 0;$SIG{INT} = 'catch_zap'; # always means &main::catch_zap$SIG{INT} = \&catch_zap; # best strategy$SIG{QUIT} = \&catch_zap; # catch another, too</pre></blockquote>Notice how all we do in the signal handler is set a global variableand then raise an exception with <tt class="literal">die</tt>. Wheneverpossible, try to avoid anything more complicated than that, because onmost systems the C library is not re-entrant. Signals are deliveredasynchronously,<a href="#FOOTNOTE-3">[3]</a>so calling any <tt class="literal">print</tt> functions (or even anythingthat needs to <em class="emphasis">malloc</em>(3) more memory)could in theory trigger a memory fault and subsequent core dump if youwere already in a related C library routine when the signal wasdelivered. (Even the <tt class="literal">die</tt> routine is a bit unsafeunless the process is executing within an <tt class="literal">eval</tt>,which suppresses the I/O from <tt class="literal">die</tt>, which keeps itfrom calling the C library. Probably.)<a name="INDEX-2903"></a><a name="INDEX-2904"></a><a name="INDEX-2905"></a><a name="INDEX-2906"></a></p><blockquote class="footnote"><a name="FOOTNOTE-3"></a><p>[3]Synchronizing signal delivery withPerl-level opcodes is scheduled for a future release of Perl, whichshould solve the matter of signals and core dumps.</p></blockquote><p><a name="INDEX-2907"></a><a name="INDEX-2908"></a><a name="INDEX-2909"></a>An even easier way to trap signals is to use the<tt class="literal">sigtrap</tt> pragma to install simple, default signalhandlers:<blockquote><pre class="programlisting">use sigtrap qw(die INT QUIT);use sigtrap qw(die untrapped normal-signals stack-trace any error-signals);</pre></blockquote><a name="INDEX-2910"></a>The pragma is useful when you don't want to bother writing your ownhandler, but you still want to catch dangerous signals and perform anorderly shutdown. By default, some of these signals are so fatal toyour process that your program will just stop in its tracks when itreceives one. Unfortunately, that means that any<tt class="literal">END</tt> functions for at-exit handling and<tt class="literal">DESTROY</tt> methods for object finalization are notcalled. But they <em class="emphasis">are</em> called on ordinary Perlexceptions (such as when you call <tt class="literal">die</tt>), so you canuse this pragma to painlessly convert the signals into exceptions.Even though you aren't dealing with the signals yourself, your programstill behaves correctly. See the description of <tt class="literal">usesigtrap</tt> in <a href="ch31_01.htm">Chapter 31, "Pragmatic Modules"</a>,for many more features of this pragma.</p><p><a name="INDEX-2911"></a><a name="INDEX-2912"></a>You may also set the <tt class="literal">%SIG</tt> handler to either of thestrings "<tt class="literal">IGNORE</tt>" or "<tt class="literal">DEFAULT</tt>",in which case Perl will try to discard the signal or allow the defaultaction for that signal to occur (though some signals can be neithertrapped nor ignored, such as the <tt class="literal">KILL</tt> and<tt class="literal">STOP</tt> signals; see<em class="emphasis">signal</em>(3), if you have it, for a list ofsignals available on your system and their default behaviors).<a name="INDEX-2913"></a></p><p><a name="INDEX-2914"></a><a name="INDEX-2915"></a>The operating system thinks of signals as numbers rather than names,but Perl, like most people, prefers symbolic names to magic numbers.To find the names of the signals, list out the keys of the<tt class="literal">%SIG</tt> hash, or use the <em class="emphasis">kill -l</em>command if you have one on your system. You can also use Perl'sstandard <tt class="literal">Config</tt> module to determine your operatingsystem's mapping between signal names and signal numbers. See<em class="emphasis">Config</em>(3) for an example of this.<a name="INDEX-2916"></a></p><p><a name="INDEX-2917"></a><a name="INDEX-2918"></a>Because <tt class="literal">%SIG</tt> is a global hash, assignments to itaffect your entire program. It's often more considerate to the restof your program to confine your signal catching to a restricted scope.Do this with a <tt class="literal">local</tt> signal handler assignment,which goes out of effect once the enclosing block is exited. (Butremember that <tt class="literal">local</tt> values are visible in functionscalled from within that block.)<blockquote><pre class="programlisting">{ local $SIG{INT} = 'IGNORE'; ... # Do whatever you want here, ignoring all SIGINTs. fn(); # SIGINTs ignored inside fn() too! ... # And here.} # Block exit restores previous $SIG{INT} value.fn(); # SIGINTs not ignored inside fn() (presumably).</pre></blockquote><a name="INDEX-2919"></a></p><h3 class="sect2">16.1.1. Signaling Process Groups</h3><p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -