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

📄 perlipc.pod

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 POD
📖 第 1 页 / 共 5 页
字号:
=head1 NAMEperlipc - Perl interprocess communication (signals, fifos, pipes, safe subprocesses, sockets, and semaphores)=head1 DESCRIPTIONThe basic IPC facilities of Perl are built out of the good old Unixsignals, named pipes, pipe opens, the Berkeley socket routines, and SysVIPC calls.  Each is used in slightly different situations.=head1 SignalsPerl uses a simple signal handling model: the %SIG hash contains namesor references of user-installed signal handlers.  These handlers willbe called with an argument which is the name of the signal thattriggered it.  A signal may be generated intentionally from aparticular keyboard sequence like control-C or control-Z, sent to youfrom another process, or triggered automatically by the kernel whenspecial events transpire, like a child process exiting, your processrunning out of stack space, or hitting file size limit.For example, to trap an interrupt signal, set up a handler like this:    sub catch_zap {	my $signame = shift;	$shucks++;	die "Somebody sent me a SIG$signame";    }    $SIG{INT} = 'catch_zap';  # could fail in modules    $SIG{INT} = \&catch_zap;  # best strategyPrior to Perl 5.7.3 it was necessary to do as little as you possiblycould in your handler; notice how all we do is set a global variableand then raise an exception.  That's because on most systems,libraries are not re-entrant; particularly, memory allocation and I/Oroutines are not.  That meant that doing nearly I<anything> in yourhandler could in theory trigger a memory fault and subsequent coredump - see L</Deferred Signals (Safe Signals)> below.The names of the signals are the ones listed out by C<kill -l> on yoursystem, or you can retrieve them from the Config module.  Set up an@signame list indexed by number to get the name and a %signo tableindexed by name to get the number:    use Config;    defined $Config{sig_name} || die "No sigs?";    foreach $name (split(' ', $Config{sig_name})) {	$signo{$name} = $i;	$signame[$i] = $name;	$i++;    }So to check whether signal 17 and SIGALRM were the same, do just this:    print "signal #17 = $signame[17]\n";    if ($signo{ALRM}) {	print "SIGALRM is $signo{ALRM}\n";    }You may also choose to assign the strings C<'IGNORE'> or C<'DEFAULT'> asthe handler, in which case Perl will try to discard the signal or do thedefault thing.On most Unix platforms, the C<CHLD> (sometimes also known as C<CLD>) signalhas special behavior with respect to a value of C<'IGNORE'>.Setting C<$SIG{CHLD}> to C<'IGNORE'> on such a platform has the effect ofnot creating zombie processes when the parent process fails to C<wait()>on its child processes (i.e. child processes are automatically reaped).Calling C<wait()> with C<$SIG{CHLD}> set to C<'IGNORE'> usually returnsC<-1> on such platforms.Some signals can be neither trapped nor ignored, such asthe KILL and STOP (but not the TSTP) signals.  One strategy fortemporarily ignoring signals is to use a local() statement, which will beautomatically restored once your block is exited.  (Remember that local()values are "inherited" by functions called from within that block.)    sub precious {	local $SIG{INT} = 'IGNORE';	&more_functions;    }    sub more_functions {	# interrupts still ignored, for now...    }Sending a signal to a negative process ID means that you send the signalto the entire Unix process-group.  This code sends a hang-up signal to allprocesses in the current process group (and sets $SIG{HUP} to IGNORE soit doesn't kill itself):    {	local $SIG{HUP} = 'IGNORE';	kill HUP => -$$;	# snazzy writing of: kill('HUP', -$$)    }Another interesting signal to send is signal number zero.  This doesn'tactually affect a child process, but instead checks whether it's aliveor has changed its UID.    unless (kill 0 => $kid_pid) {	warn "something wicked happened to $kid_pid";    }When directed at a process whose UID is not identical to thatof the sending process, signal number zero may fail becauseyou lack permission to send the signal, even though the process is alive.You may be able to determine the cause of failure using C<%!>.    unless (kill 0 => $pid or $!{EPERM}) {	warn "$pid looks dead";    }You might also want to employ anonymous functions for simple signalhandlers:    $SIG{INT} = sub { die "\nOutta here!\n" };But that will be problematic for the more complicated handlers that needto reinstall themselves.  Because Perl's signal mechanism is currentlybased on the signal(3) function from the C library, you may sometimes be sounfortunate as to run on systems where that function is "broken", thatis, it behaves in the old unreliable SysV way rather than the newer, morereasonable BSD and POSIX fashion.  So you'll see defensive people writingsignal handlers like this:    sub REAPER {	$waitedpid = wait;	# loathe sysV: it makes us not only reinstate	# the handler, but place it after the wait	$SIG{CHLD} = \&REAPER;    }    $SIG{CHLD} = \&REAPER;    # now do something that forks...or better still:    use POSIX ":sys_wait_h";    sub REAPER {	my $child;	# If a second child dies while in the signal handler caused by the	# first death, we won't get another signal. So must loop here else	# we will leave the unreaped child as a zombie. And the next time	# two children die we get another zombie. And so on.        while (($child = waitpid(-1,WNOHANG)) > 0) {	    $Kid_Status{$child} = $?;	}	$SIG{CHLD} = \&REAPER;  # still loathe sysV    }    $SIG{CHLD} = \&REAPER;    # do something that forks...Signal handling is also used for timeouts in Unix,   While safelyprotected within an C<eval{}> block, you set a signal handler to trapalarm signals and then schedule to have one delivered to you in somenumber of seconds.  Then try your blocking operation, clearing the alarmwhen it's done but not before you've exited your C<eval{}> block.  If itgoes off, you'll use die() to jump out of the block, much as you mightusing longjmp() or throw() in other languages.Here's an example:    eval {        local $SIG{ALRM} = sub { die "alarm clock restart" };        alarm 10;        flock(FH, 2);   # blocking write lock        alarm 0;    };    if ($@ and $@ !~ /alarm clock restart/) { die }If the operation being timed out is system() or qx(), this techniqueis liable to generate zombies.    If this matters to you, you'llneed to do your own fork() and exec(), and kill the errant child process.For more complex signal handling, you might see the standard POSIXmodule.  Lamentably, this is almost entirely undocumented, butthe F<t/lib/posix.t> file from the Perl source distribution has someexamples in it.=head2 Handling the SIGHUP Signal in DaemonsA process that usually starts when the system boots and shuts downwhen the system is shut down is called a daemon (Disk And ExecutionMONitor). If a daemon process has a configuration file which ismodified after the process has been started, there should be a way totell that process to re-read its configuration file, without stoppingthe process. Many daemons provide this mechanism using the C<SIGHUP>signal handler. When you want to tell the daemon to re-read the fileyou simply send it the C<SIGHUP> signal.Not all platforms automatically reinstall their (native) signalhandlers after a signal delivery.  This means that the handler worksonly the first time the signal is sent. The solution to this problemis to use C<POSIX> signal handlers if available, their behaviouris well-defined.The following example implements a simple daemon, which restartsitself every time the C<SIGHUP> signal is received. The actual code islocated in the subroutine C<code()>, which simply prints some debuginfo to show that it works and should be replaced with the real code.  #!/usr/bin/perl -w  use POSIX ();  use FindBin ();  use File::Basename ();  use File::Spec::Functions;  $|=1;  # make the daemon cross-platform, so exec always calls the script  # itself with the right path, no matter how the script was invoked.  my $script = File::Basename::basename($0);  my $SELF = catfile $FindBin::Bin, $script;  # POSIX unmasks the sigprocmask properly  my $sigset = POSIX::SigSet->new();  my $action = POSIX::SigAction->new('sigHUP_handler',                                     $sigset,                                     &POSIX::SA_NODEFER);  POSIX::sigaction(&POSIX::SIGHUP, $action);  sub sigHUP_handler {      print "got SIGHUP\n";      exec($SELF, @ARGV) or die "Couldn't restart: $!\n";  }  code();  sub code {      print "PID: $$\n";      print "ARGV: @ARGV\n";      my $c = 0;      while (++$c) {          sleep 2;          print "$c\n";      }  }  __END__=head1 Named PipesA named pipe (often referred to as a FIFO) is an old Unix IPCmechanism for processes communicating on the same machine.  It worksjust like a regular, connected anonymous pipes, except that theprocesses rendezvous using a filename and don't have to be related.To create a named pipe, use the C<POSIX::mkfifo()> function.    use POSIX qw(mkfifo);    mkfifo($path, 0700) or die "mkfifo $path failed: $!";You can also use the Unix command mknod(1) or on somesystems, mkfifo(1).  These may not be in your normal path.    # system return val is backwards, so && not ||    #    $ENV{PATH} .= ":/etc:/usr/etc";    if  (      system('mknod',  $path, 'p')	    && system('mkfifo', $path) )    {	die "mk{nod,fifo} $path failed";    }A fifo is convenient when you want to connect a process to an unrelatedone.  When you open a fifo, the program will block until there's somethingon the other end.For example, let's say you'd like to have your F<.signature> file be anamed pipe that has a Perl program on the other end.  Now every time anyprogram (like a mailer, news reader, finger program, etc.) tries to readfrom that file, the reading program will block and your program willsupply the new signature.  We'll use the pipe-checking file test B<-p>to find out whether anyone (or anything) has accidentally removed our fifo.    chdir; # go home    $FIFO = '.signature';    while (1) {	unless (-p $FIFO) {	    unlink $FIFO;	    require POSIX;	    POSIX::mkfifo($FIFO, 0700)		or die "can't mkfifo $FIFO: $!";	}	# next line blocks until there's a reader	open (FIFO, "> $FIFO") || die "can't write $FIFO: $!";	print FIFO "John Smith (smith\@host.org)\n", `fortune -s`;	close FIFO;	sleep 2;    # to avoid dup signals    }=head2 Deferred Signals (Safe Signals)In Perls before Perl 5.7.3 by installing Perl code to deal withsignals, you were exposing yourself to danger from two things.  First,few system library functions are re-entrant.  If the signal interruptswhile Perl is executing one function (like malloc(3) or printf(3)),and your signal handler then calls the same function again, you couldget unpredictable behavior--often, a core dump.  Second, Perl isn'titself re-entrant at the lowest levels.  If the signal interrupts Perlwhile Perl is changing its own internal data structures, similarlyunpredictable behaviour may result.There were two things you could do, knowing this: be paranoid or bepragmatic.  The paranoid approach was to do as little as possible in yoursignal handler.  Set an existing integer variable that already has avalue, and return.  This doesn't help you if you're in a slow system call,which will just restart.  That means you have to C<die> to longjmp(3) outof the handler.  Even this is a little cavalier for the true paranoiac,who avoids C<die> in a handler because the system I<is> out to get you.The pragmatic approach was to say "I know the risks, but prefer theconvenience", and to do anything you wanted in your signal handler,and be prepared to clean up core dumps now and again.In Perl 5.7.3 and later to avoid these problems signals are"deferred"-- that is when the signal is delivered to the process bythe system (to the C code that implements Perl) a flag is set, and thehandler returns immediately. Then at strategic "safe" points in thePerl interpreter (e.g. when it is about to execute a new opcode) theflags are checked and the Perl level handler from %SIG isexecuted. The "deferred" scheme allows much more flexibility in thecoding of signal handler as we know Perl interpreter is in a safestate, and that we are not in a system library function when thehandler is called.  However the implementation does differ fromprevious Perls in the following ways:=over 4=item Long-running opcodesAs the Perl interpreter only looks at the signal flags when it is aboutto execute a new opcode, a signal that arrives during a long-runningopcode (e.g. a regular expression operation on a very large string) willnot be seen until the current opcode completes.N.B. If a signal of any given type fires multiple times during an opcode (such as from a fine-grained timer), the handler for that signal willonly be called once after the opcode completes, and all the otherinstances will be discarded.  Furthermore, if your system's signal queuegets flooded to the point that there are signals that have been raisedbut not yet caught (and thus not deferred) at the time an opcodecompletes, those signals may well be caught and deferred duringsubsequent opcodes, with sometimes surprising results.  For example, you

⌨️ 快捷键说明

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