📄 ch14.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 14 -- Signals, Pipes, FIFOs, and Perl</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 14</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Signals, Pipes, FIFOs, and Perl</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#Signals" >Signals</A>
<UL>
<LI><A HREF="#UsingtheConfigModule" >Using the Config Module</A>
</UL>
<LI><A HREF="#ThekillFunction" >The kill() Function</A>
<LI><A HREF="#ThewarnFunction" >The warn() Function</A>
<LI><A HREF="#Timeouts" >Timeouts</A>
<LI><A HREF="#PipesandFIFOs" >Pipes and FIFOs</A>
<LI><A HREF="#UsingopenforIpc" >Using open() for Ipc</A>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
The basic interprocess communication facilities available via
Perl are built on the old UNIX facilities: signals, named pipes,
pipe opens, the Berkeley socket routines, and SysV Ipc calls.
I have already covered sockets, shared memory, semaphores, and
message queues in the previous sections. I cover the use of signals
and pipes in this chapter.
<H2><A NAME="Signals"><FONT SIZE=5 COLOR=#FF0000>Signals</FONT></A>
</H2>
<P>
A <I>signal</I> is a message sent to a process that indicates
an event has occurred. The event can be something unexpected and,
in general, cause the process to terminate. Types of such signal
events include division by zero, a bus error, a segmentation fault,
or sometimes even imminent power failure. All signals are not
bad news. UNIX kernels use signals for timing. Users can send
signals by hitting keys such as Ctrl+C, Break, or Delete.
<P>
The types of signals recognized by the kernel are listed in the
standard UNIX header file <TT><FONT FACE="Courier">/usr/include/signal.h</FONT></TT>.
The names of these signals are listed in Table 14.1. Not all of
these signals may be implemented in your UNIX system, and even
fewer are usable in Perl. However, I will cover all the signals
that you definitely need to know.<BR>
<P>
<CENTER><B>Table 14.1 Signal types.</B></CENTER>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR VALIGN=TOP><TD WIDTH=109><I>Signal</I></TD><TD WIDTH=73><CENTER><I>Number</I></CENTER>
</TD><TD WIDTH=250><I>Description</I></TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGHUP</FONT></TT>
</TD><TD WIDTH=73><CENTER>1</CENTER></TD><TD WIDTH=250>On hangup
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGINT</FONT></TT>
</TD><TD WIDTH=73><CENTER>2</CENTER></TD><TD WIDTH=250>On interrupt
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGQUIT</FONT></TT>
</TD><TD WIDTH=73><CENTER>3</CENTER></TD><TD WIDTH=250>On Quit key
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGILL</FONT></TT>
</TD><TD WIDTH=73><CENTER>4</CENTER></TD><TD WIDTH=250>Illegal instruction
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGTRAP</FONT></TT>
</TD><TD WIDTH=73><CENTER>5</CENTER></TD><TD WIDTH=250>Trap instruction
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGABRT</FONT></TT>
</TD><TD WIDTH=73><CENTER>6</CENTER></TD><TD WIDTH=250>Abort message
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGIOT</FONT></TT>
</TD><TD WIDTH=73><CENTER>6</CENTER></TD><TD WIDTH=250>Input/output transfer
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGBUS</FONT></TT>
</TD><TD WIDTH=73><CENTER>7</CENTER></TD><TD WIDTH=250>Bus error
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGFPE</FONT></TT>
</TD><TD WIDTH=73><CENTER>8</CENTER></TD><TD WIDTH=250>Floating-point error
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGKILL</FONT></TT>
</TD><TD WIDTH=73><CENTER>9</CENTER></TD><TD WIDTH=250>Kill signal from system
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGUSR1</FONT></TT>
</TD><TD WIDTH=73><CENTER>10</CENTER></TD><TD WIDTH=250>User defined
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGSEGV</FONT></TT>
</TD><TD WIDTH=73><CENTER>11</CENTER></TD><TD WIDTH=250>Segmentation violation
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGUSR2</FONT></TT>
</TD><TD WIDTH=73><CENTER>12</CENTER></TD><TD WIDTH=250>User defined
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGPIPE</FONT></TT>
</TD><TD WIDTH=73><CENTER>13</CENTER></TD><TD WIDTH=250>Pipe fault (broken pipe)
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGALRM</FONT></TT>
</TD><TD WIDTH=73><CENTER>14</CENTER></TD><TD WIDTH=250>Alarm
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGTERM</FONT></TT>
</TD><TD WIDTH=73><CENTER>15</CENTER></TD><TD WIDTH=250>Termination
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGSTKFLT</FONT></TT>
</TD><TD WIDTH=73><CENTER>16</CENTER></TD><TD WIDTH=250>Stack fault
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGchLD</FONT></TT>
</TD><TD WIDTH=73><CENTER>17</CENTER></TD><TD WIDTH=250>Signal from child
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGCONT</FONT></TT>
</TD><TD WIDTH=73><CENTER>18</CENTER></TD><TD WIDTH=250>Continuing a stopped process
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGSTOP</FONT></TT>
</TD><TD WIDTH=73><CENTER>19</CENTER></TD><TD WIDTH=250>Stopping a process
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGTSTP</FONT></TT>
</TD><TD WIDTH=73><CENTER>20</CENTER></TD><TD WIDTH=250>Stopping a process from terminal
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGTTIN</FONT></TT>
</TD><TD WIDTH=73><CENTER>21</CENTER></TD><TD WIDTH=250>Stopping a process reading from controlling terminal
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGTTOU</FONT></TT>
</TD><TD WIDTH=73><CENTER>22</CENTER></TD><TD WIDTH=250>Stopping a process writing to controlling terminal
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGURG</FONT></TT>
</TD><TD WIDTH=73><CENTER>23</CENTER></TD><TD WIDTH=250>Urgent condition
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGXCPU</FONT></TT>
</TD><TD WIDTH=73><CENTER>24</CENTER></TD><TD WIDTH=250>Excessive CPU limits reached
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGXFSZ</FONT></TT>
</TD><TD WIDTH=73><CENTER>25</CENTER></TD><TD WIDTH=250>Excessive file size limits reached
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGVTALRM</FONT></TT>
</TD><TD WIDTH=73><CENTER>26</CENTER></TD><TD WIDTH=250>Virtual interval timer expired
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGPROF</FONT></TT>
</TD><TD WIDTH=73><CENTER>27</CENTER></TD><TD WIDTH=250>Profiling interval timer expired
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGWINch</FONT></TT>
</TD><TD WIDTH=73><CENTER>28</CENTER></TD><TD WIDTH=250>Window size changed by background process
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGIO</FONT></TT></TD>
<TD WIDTH=73><CENTER>29</CENTER></TD><TD WIDTH=250>Asynchronous I/O
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGPWR</FONT></TT>
</TD><TD WIDTH=73><CENTER>30</CENTER></TD><TD WIDTH=250>Power failure
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=109><TT><FONT FACE="Courier">SIGUNUSED</FONT></TT>
</TD><TD WIDTH=73><CENTER>31</CENTER></TD><TD WIDTH=250>Unused
</TD></TR>
</TABLE></CENTER>
<P>
<P>
The names of the signals available to you on your system are the
ones listed by <TT><FONT FACE="Courier">kill -l</FONT></TT> on
your system. You can also retrieve them from the <TT><FONT FACE="Courier">Config</FONT></TT>
module. The following example shows how to obtain a list of available
signals on your system:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>kill -l<BR>
</B> 1) SIGHUP 2)
SIGINT 3) SIGQUIT 4)
SIGILL<BR>
5) SIGTRAP
6) SIGIOT 7) SIGBUS
8) SIGFPE<BR>
9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2<BR>
13) SIGPIPE 14) SIGALRM
15) SIGTERM 17) SIGchLD<BR>
18) SIGCONT 19) SIGSTOP
20) SIGTSTP 21) SIGTTIN<BR>
22) SIGTTOU 23) SIGURG 24)
SIGXCPU 25) SIGXFSZ<BR>
26) SIGVTALRM 27) SIGPROF
28) SIGWINch 29) SIGIO<BR>
30) SIGPWR</FONT></TT>
</BLOCKQUOTE>
<H3><A NAME="UsingtheConfigModule">Using the <TT><FONT SIZE=4 FACE="Courier">Config</FONT></TT><FONT SIZE=4>
Module</FONT></A></H3>
<P>
Another way of getting a list of signals on your system is by
using the supplied <TT><FONT FACE="Courier">Config</FONT></TT>
module, as shown in Listing 14.1. The output from this simple
script is shown following the listing. The list of signal names
in the <TT><FONT FACE="Courier">Config</FONT></TT> module is accessed
via the <TT><FONT FACE="Courier">$Config{sig_name}</FONT></TT>
variable. (The signal names are separated by white space.) By
the way, the program shown in Listing 14.1 requires Perl 5 and
will not work in Perl 4.
<HR>
<BLOCKQUOTE>
<B>Listing 14.1. Using the </B><TT><B><FONT FACE="Courier">Config</FONT></B></TT><B>
module to get a list of signals.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2 #<BR>
3 # Use the Config
module to get list of signals<BR>
4<BR>
5 use Config;<BR>
6<BR>
7 defined $Config{sig_name}
|| die "No Config Module?";<BR>
8<BR>
9 foreach $name (split('
', $Config{sig_name})) {<BR>
10 $i++;<BR>
11 printf "%3d) %s \t", $i,
$name;<BR>
12 if (($i % 5) == 0) { print "\n"; }
<BR>
13 }<BR>
14 print "\n";</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Line 5 uses the <TT><FONT FACE="Courier">Config</FONT></TT> module
to include its definitions. The existence of the <TT><FONT FACE="Courier">Config</FONT></TT>
signal names array is confirmed in line 7. Lines 9 through 14
print out a columnar output of all the signal names defined in
the <TT><FONT FACE="Courier">Config</FONT></TT> array. Here is
the output generated by the code in Listing 14.1.
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$ <B>listsigs.pl<BR>
<BR>
</B> 1) ZERO
2) HUP 3) INT 4)
QUIT 5) ILL<BR>
6) TRAP 7) IOT
8) BUS 9) FPE
10) KILL<BR>
11) USR1 12)
SEGV 13) USR2 14)
PIPE 15) ALRM<BR>
16) TERM 17) STKFLT 18)
chLD 19) CONT 20)
STOP<BR>
21) TSTP 22)
TTIN 23) TTOU 24)
URG 25) XCPU<BR>
26) XFSZ 27) VTALRM 28)
PROF 29) WINch
30) LOST<BR>
31) PWR 32) UNUSED</FONT></TT>
</BLOCKQUOTE>
<P>
A process does not know when a signal might occur because signals
are asynchronous events. Programmatically, you can either ignore
almost all signal messages or handle them yourself with a signal
handler. This process of handling the signal is referred to as
<I>trapping a signal</I>. A handler is simply a function that
is called when the signal arrives.
<P>
In Perl, a special hash called <TT><FONT FACE="Courier">%SIG</FONT></TT>
contains either names or references to all the signal handlers.
You have to install your own signal handler to trap a signal.
If you do install a handler, Perl uses the default handling mechanism
for that signal. Signal handlers are considered by the Perl interpreter
to be in the main module unless otherwise specified. To specify
a different module, you have to specify the package name. Therefore,
you would use something like this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$SIG{'QUIT'} = 'myModule::babysitter';</FONT></TT>
</BLOCKQUOTE>
<P>
Signal handlers are basically just Perl functions. However, some
restrictions apply while you are in the handler. First of all,
signal handlers are called with an argument that is the name of
the signal that triggered it. Therefore, your handler can be written
to trap more than one signal if you want. Simply use the passed
argument to determine what to do in the handler. Next, if your
signal handler is being called when something out of the ordinary
happens, you should not attempt to do lengthy operations while
in the handler. For example, doing lengthy disk writes within
a handler is <I>not</I> a good idea. Finally, try to use references
instead of names because the code is cleaner and faster.
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -