my @who_lines = `who`; # 返回的多个在线用户及其信息按照原始输出的样子分成多行进入array
并行进程——将进程当作file handles
== 并行进程
用system和exec都是使用的同步进程方式,也就是perl启动一个进程,然后perl等待他完成,获得返回值,然后perl才能继续执行。
但是实际上,我们可以使用并行进程。也就是perl进程本身和该进程同时运行。
并行进程的好处是,产生的结果实时获取,看起来比较真实,和实际shell执行比较吻合,而同步进程则必须等待子进程全部执行完毕,才返回结果。
采用下面的结构就可以实时获取输出并实时处理。
open FH, "...command...";
while (<FH>) { ... processing... }
== 并行进程(作为perl的输入进程)
open DATE, "date|" or die "can not pipe from date: $!";
my $now = <DATE>;
上面的例子将进程作为file handle,并通过这个file handle来获得数据。
为了从这个file handle 获得数据。我们必须在程序名称右侧添加"|"符号,表示perl程序将通过该进程的pipe输出来获得数据。
== 并行进程(作为perl的输出进程)
open MAIL, "|mail merlyn" or die "Can not pipe to mail: $!";
print MAIL, "The time is: $now";
上面的例子将进程作为file handle,并向这个file handle输入数据。
为了向这个file handle 输入数据。
我们必须在程序名称坐侧添加"|"符号,表示perl程序将通过该进程的pipe向其输入数据。
对于mail程序来说,这个file handle就是其标准输入。
== 并行进程的关闭
close MAIL; die "mail: nonzero exit of $?" if $?;
对于接收输入型进程来说。close命令就意味着发出一个EOF。 $?是进程的退出状态。
一般,0表示成功。非零表示失败。
看看进程调用的底层实现
== system "date"; 的底层实现
defined(my $pid = fork) or die "cannot fork: $!";
unless ($pid) { # 子进程从这儿开始
exec "date";
die "can not exec date: $!";
}
# 父进程在此
waitpid ($pid, 0);
收发信号
== 信号的样子
不同的信号用不同的名字标识(比如SIGINT表示一个中断信号),并且每个信号对应一个整数,整数的范围和具体的unit系统有关。
== 信号的来源
信号在某些重要事件发生时被发送。
比如按下Ctrl+C,就传递一个中断SIGINT到所有和当前的terminal相关的进程。
== 主动发送信号
Perl可以给其他进程主动发送信号。
比如要发送SIGINT到进程4201,就可以这样写
kill 2, 4201 or die "Cannot signal 4201 with SIGINT: $!";
发送信号的命令被命名为 kill ,因为信号的主要目的是终止一个进程。
== kill进程操作的返回值
如果进程别消灭,则返回 false 。
表示已经不存在。所以可以用下面代码检查kill的结果。
unless (kell 0, $pid) { warn "process $pid has gone away!" }
== 如何接收信号并响应
看一个例子。
sub my_int_handler {
# (中断)信号处理程序
&clean_up;
die "interrupted, exiting...\n"; }
$SIG{‘INT‘} = ‘my_int_handler‘; # 指定SIGINT信号的处理程序为 my_int_handler
.
. # 程序运行中
. # 这时有人按下了Ctrl+C,向本进程传来 SIGINT信号 .
# 正常执行的结尾处
&clean_up; 注意名为%SIG的hash表储存了一个信号处理mapping表。key是各类信号,value是相关处理子程序。
== Perl收到信号如何响应
Perl会停止当前的执行,然后跳到信号处理程序处,完成后再返回原来的位置。