Welcome to jaever.com/diary

Wget非交互式的网络文件下载工具

GNU Wget 1.10.2,非交互式的网络文件下载工具。
用法: wget [选项]... [URL]...

Mandatory arguments to long options are mandatory for short options too.

开始:
 -V,  --version  显示Wget版本之后退出。
 -h,  --help      显示本帮助
 -b,  --background        启动后转到后台运行。
 -e,  --execute=COMMAND   运行 `.wgetrc'-那样的命令。

日志和输入文件:
 -o,  --output-file=FILE    将日志记录到文件 FILE.
 -a,  --append-output=FILE  添加消息到文件 FILE.
 -d,  --debug               输出大量调试信息。
 -q,  --quiet               静默模式 (无输出)。
 -v,  --verbose             显示信息 (默认打开).
 -nv, --no-verbose          显示很少信息但不是完全安静.
 -i,  --input-file=FILE     下载存储在 FILE 文件中的所有URL地址指向的文件。
 -F,  --force-html          把输入文件当成 HTML.
 -B,  --base=URL            prepends URL to relative links in -F -i file.

下载:
 -t,  --tries=NUMBER            设定重试次数(0 一直重试)。
      --retry-connrefused       retry even if connection is refused.
 -O,  --output-document=FILE    写入文档到 FILE.
 -nc, --no-clobber              跳过将要到已存在文件的下载。
 -c,  --continue 续传下载。
      --progress=TYPE           select progress gauge type.
 -N,  --timestamping            don't re-retrieve files unless newer than
                                local.
 -S, --server-response 显示服务器的响应。
      --spider                  什么都不下载
 -T, --timeout=SECONDS 把所有超时时间设为SECONDS秒。
      --dns-timeout=SECS 把DNS超时时间设为SECS秒。
      --connect-timeout=SECS    设定连接超时为 SECS.
      --read-timeout=SECS       设定读取超时为 SECS.
 -w,  --wait=SECONDS            wait SECONDS between retrievals.
      --waitretry=SECONDS       wait 1..SECONDS between retries of a retrieval.
      --random-wait             wait from 0...2*WAIT secs between retrievals.
 -Y,  --proxy                   显示打开代理
      --no-proxy                显示关闭代理
 -Q,  --quota=NUMBER            set retrieval quota to NUMBER.
      --bind-address=ADDRESS    bind to ADDRESS (hostname or IP) on local host.
      --limit-rate=RATE 把下载速度限制为RATE。
      --no-dns-cache 禁止查找DNS缓存。
      --restrict-file-names=OS  restrict chars in file names to ones OS allows.
 -4, --inet4-only 仅连接IPv4地址。
 -6,  --inet6-only              只连接到 IPv6 地址。
      --prefer-family=FAMILY    connect first to addresses of specified family,
                                one of IPv6, IPv4, or none.
      --user=USER 把ftp和http的用户名设定为UESR。
      --password=PASS 把ftp和http的密码设定为PASS。

目录:
 -nd,--no-directories 不建立文件夹。
 -x,--force-directories 强制建立文件夹。
 -nH, --no-host-directories      不创建主机目录。
      --protocol-directories     use protocol name in directories.
 -P,  --directory-prefix=PREFIX  将文件保存到 PREFIX/...
      --cut-dirs=NUMBER          ignore NUMBER remote directory components.

HTTP 选项:
      --http-user=USER        将 http用户设为 USER.
      --http-password=PASS    将http密码设为 PASS.
      --no-cache              不接受服务器缓存的数据.
 -E,--html-extension 以'.html'扩展名保存HTML文档。
      --ignore-length         ignore `Content-Length' header field.
      --header=STRING         insert STRING among the headers.
      --proxy-user=USER       设定 USER 作为代理用户名。
      --proxy-password=PASS   设定 PASS 作为代理密码。
      --referer=URL           include `Referer: URL' header in HTTP request.
      --save-headers          保存 HTTP 头到文件。
 -U,  --user-agent=AGENT      identify as AGENT instead of Wget/VERSION.
      --no-http-keep-alive    disable HTTP keep-alive (persistent connections).
      --no-cookies            不使用cookies.
      --load-cookies=FILE 在会话前从文件中读取cookies。
      --save-cookies=FILE     在会话结束后保存 cookies 到 FILE。
      --keep-session-cookies  load and save session (non-permanent) cookies.
      --post-data=STRING      use the POST method; send STRING as the data.
      --post-file=FILE        use the POST method; send contents of FILE.

HTTPS (SSL/TLS) 选项:
      --secure-protocol=PR     choose secure protocol, one of auto, SSLv2,
                               SSLv3, and TLSv1.
      --no-check-certificate   don't validate the server's certificate.
      --certificate=FILE       client certificate file.
      --certificate-type=TYPE  client certificate type, PEM or DER.
      --private-key=FILE       private key file.
      --private-key-type=TYPE  private key type, PEM or DER.
      --ca-certificate=FILE    file with the bundle of CA's.
      --ca-directory=DIR       directory where hash list of CA's is stored.
      --random-file=FILE       file with random data for seeding the SSL PRNG.
      --egd-file=FILE          file naming the EGD socket with random data.

FTP 选项:
      --ftp-user=USER         设置ftp用户为 USER.
      --ftp-password=PASS     设置ftp密码为 PASS.
      --no-remove-listing     don't remove `.listing' files.
      --no-glob               turn off FTP file name globbing.
      --no-passive-ftp        disable the "passive" transfer mode.
      --retr-symlinks         when recursing, get linked-to files (not dir).
      --preserve-permissions  preserve remote file permissions.

递归下载:
 -r,  --recursive          specify recursive download.
 -l,  --level=NUMBER       maximum recursion depth (inf or 0 for infinite).
      --delete-after       delete files locally after downloading them.
 -k,  --convert-links      make links in downloaded HTML point to local files.
 -K,  --backup-converted   before converting file X, back up as X.orig.
 -m,  --mirror             shortcut for -N -r -l inf --no-remove-listing.
 -p,  --page-requisites    get all images, etc. needed to display HTML page.
      --strict-comments    turn on strict (SGML) handling of HTML comments.

Recursive accept/reject:
 -A,  --accept=LIST               comma-separated list of accepted extensions.
 -R,  --reject=LIST               comma-separated list of rejected extensions.
 -D,  --domains=LIST              comma-separated list of accepted domains.
      --exclude-domains=LIST      被拒绝的域名的用逗号分开的列表。
      --follow-ftp                follow FTP links from HTML documents.
      --follow-tags=LIST          comma-separated list of followed HTML tags.
      --ignore-tags=LIST          comma-separated list of ignored HTML tags.
 -H,  --span-hosts                当递归时转到陌生的主机。
 -L,  --relative                  只跟随相对链接。
 -I,  --include-directories=LIST  允许的目录的列表。
 -X,  --exclude-directories=LIST  不包括的目录的列表。
 -np, --no-parent                 don't ascend to the parent directory.

CONTINUE
INFO: 2008-09-05 02:21:21 | purpen | digg | link

[转载]说一说羽毛球的几种概念

手指发力:是指在球拍与球接触刹那,通过手指突然收紧,产生力量,使球拍面方向转换或加快挥拍速度。 应用:该项发力是击球动作最重要的一个环节,它是调整击球方向和调整击球距离的关键,也是快速提高技能的捷径。 1、捻动发力:动作如关水阀门,四指以顺时针方向旋转来搓动球拍柄,使拍面旋转。 应用:主要应用于网前力量较小的搓、推等动作。 2、屈指发力:拇指、食指扣紧拍柄为支点,其余三指由松到屈指握紧发力。 应用:主要用于需发力的动作,如高远球、平高球、抽球、杀球等。 3、屈捻发力:其动作界于上面两者之间,所发力量要比捻动大而比屈指发力小,是上述两者动作的结合。 应用:多用于后场的吊球、劈吊。 4、小臂的内旋与外旋:把手掌平放,让手背朝上的动作即为内旋,从手背转到手心即为外旋。 应用:此动作多用于高远球、平高球、杀球、抽球等动作的发力,其作用一为调整击球的拍面,二为增加击球瞬间的爆发力。 5、手腕的内收与外展:将手臂平放,手掌直立形同握手,手掌向上抬为外展,向下压为内收。 应用:多用于反手击球。 6、手腕的前屈、后伸发力:将手臂平放,手背朝上,当手腕向下压时为前屈,手腕向上抬为后伸。 应用:后场大力杀球、平高球、挑球等动作。 7、拉拍:手臂上举伸直,然后沉肘,使球拍向前下方运动。 应用:多用于击球点较低时击球,属于被动击球。如中场平抽球,近网球,后场的过渡球或在假动作中出现。 该动作的使用应特别注意,在主动击球时极少使用,但因该动作能产生较大的爆发力,故许多选手已习惯性使用,并使主动击球动作变形,影响技术的发展和攻击力的减弱。 8、起动:是在比赛场上使用最多的动作,也是胜负关键的一环。其动作为持拍手侧的脚略靠前,另一脚后撤半个脚(特殊情况除外),准备时,两脚不能站实(即以全脚掌着地),这样不利于蹬地起动,而应稍提脚跟,双膝微屈,沉肩坐腰,持拍于胸腹之间,并使两脚保持微动。起动一刹那要注意调整重心。一般为重心与去的去的方向相反。如要上右手网前,重心应先移至左脚,要上左手网前,重心移至右脚,这样是为了产生爆发力,提高起动速度。 CONTINUE
INFO: 2008-09-04 06:49:48 | purpen | digg | link

[转载]在Nginx环境下用Perl FastCGI支持Awstats

日志统计分析软件Awstats需要Perl支持,但是Nginx内建的Perl模块目前还并不稳定,经常会出问题,所以还是用FastCGI模式运行Perl比较可靠。下面就谈谈如何在Nginx下配置Perl的FastCGI模式:

首先,安装Perl的FastCGI模块:

#wget http://www.cpan.org/modules/by-module/FCGI/FCGI-0.67.tar.gz
#tar zxvf FCGI-0.67.tar.gz
#cd FCGI-0.67
# perl Makefile.PL
#make && make install

其实也可以用这种方法:#perl -MCPAN -e ‘install FCGI’

然后,配置Perl的FastCGI脚本(从网上找到的,未找到原始出处):

#!/usr/bin/perl
use FCGI;
use Socket;
use POSIX qw(setsid);
require ’syscall.ph’;
&daemonize;
END() { } BEGIN() { }
*CORE::GLOBAL::exit = sub { die “fakeexit\nrc=”.shift().”\n”; };
eval q{exit};
if ($@) {
exit unless $@ =~ /^fakeexit/;
};
&main;
sub daemonize() {
chdir ‘/’ or die “Can’t chdir to /: $!”;
defined(my $pid = fork) or die “Can’t fork: $!”;
exit if $pid;
setsid or die “Can’t start a new session: $!”;
umask 0;
}
sub main {
$socket = FCGI::OpenSocket( “/tmp/perl_fastcgi.sock”, 10 );
$request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket );
if ($request) { request_loop()};
FCGI::CloseSocket( $socket );
}
sub request_loop {
while( $request->Accept() >= 0 ) {
$stdin_passthrough =”;
$req_len = 0 + $req_params{’CONTENT_LENGTH’};
if (($req_params{’REQUEST_METHOD’} eq ‘POST’) && ($req_len != 0) ){
my $bytes_read = 0;
while ($bytes_read < $req_len) {
my $data = '';
my $bytes = read(STDIN, $data, ($req_len - $bytes_read));
last if ($bytes == 0 || !defined($bytes));
$stdin_passthrough .= $data;
$bytes_read += $bytes;
}
}
if ( (-x $req_params{SCRIPT_FILENAME}) &&
(-s $req_params{SCRIPT_FILENAME}) &&
(-r $req_params{SCRIPT_FILENAME})
){
pipe(CHILD_RD, PARENT_WR);
my $pid = open(KID_TO_READ, "-|");
unless(defined($pid)) {
print("Content-type: text/plain\r\n\r\n");
print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";
next;
}
if ($pid > 0) {
close(CHILD_RD);
print PARENT_WR $stdin_passthrough;
close(PARENT_WR);
while(my $s = ) { print $s; }
close KID_TO_READ;
waitpid($pid, 0);
} else {
foreach $key ( keys %req_params){
$ENV{$key} = $req_params{$key};
}
if ($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) {
chdir $1;
}

close(PARENT_WR);
close(STDIN);
syscall(&SYS_dup2, fileno(CHILD_RD), 0);
exec($req_params{SCRIPT_FILENAME});
die(”exec failed”);
}
}
else {
print(”Content-type: text/plain\r\n\r\n”);
print “Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n”;
}

}
}

将权限改为可执行,并执行之。

配置nginx.conf,使之支持perl脚本:

location ~* .*\.pl$
{
include awstats.conf;
}

编辑awstats.conf

fastcgi_pass unix:/tmp/perl_fastcgi.sock;
fastcgi_index awstats.pl;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_read_timeout 60;

然后重启nginx:
#service nginx restart

CONTINUE
INFO: 2008-09-04 06:45:15 | purpen | digg | link

[转载]A Beginner's Introduction to POE

What Is POE, And Why Should I Use It?
    回顾一下我们每天写的程序,可以发现这些程序大部分都有着基本的结构:启动,执行一系列的动作,然后退出。对于那些在用户和他们的数据之间不需要很多交互的应用中,这样的程序都能工作得很好。然后,如果是如果是碰到了复杂的任务,我想你就需要一个更加好的程序框架理解任务的复杂性,完成这个任务。
    所以POE(Perl 对象环境)应运而生了。POE是一个构建Perl程序的框架,以更自然地完成那些需要对外部数据作出反应的任务,比如网络通讯或者用户接口。用POE写的程序完全是非线性的;你只需要建立一些小的子程序,并且定义好它们之间如何相互调用,那么POE就会根据程序处理的输入输出,自动在它们之间切换。说到现在,你可能已经头晕了。如果你习惯于看代码去理解,那么看了下面一个小例子后,你就会恍然大悟了。

POE Design
    说POE是一个小的操作系统一点都不夸张,它有它自己的内核,进程,进程间通讯(IPC),驱动等等这些。实际上,它是一个简单的系统,构建了一系列的状态信息。下面对组成POE各个部分的一个简单的描述:
States
    POE的基本程序块就是状态,它是一些代码,当事件发生时触发执行。例如,输入的数据到达,一个会话过期,一个会话传递了一条信息给另一个会话。POE里的每件事情都是基于接收和处理各种各样的事件。
The Kernel
    POE的内核跟操作系统的内核很象:它守护着后台的所有你的进程和数据,安排你的代码的触发。你能够用POE的内核来为你的进程设置警报,控制你的状态队列和其他一些低级服务,当然,大部分时间你不用直接来跟内核交互。
Sessions
    POE里的会话相当于一个真的操作系统里的进程。一个会话就是一个POE程序,当它在运行时不停地在状态之间切换。它能够创建子会话,传递信息给其他的会话等等。每个会话都能通过调用 heap 存储会话特有的数据,这些数据在会话中的各个状态都是可以存取的。
    POE有一个简单的协作的多任务处理模块;每个会话在同一个OS进程中执行,不需要任何线程和进程。对于这样的会话,你应该特别注意在POE程序中使用模块化的系统调用。
    这些就是POE的最基本的部分,但是在我们开始实际的代码前还需要稍微ie解释一些高级的POE的部分。
Drivers
    驱动位于POE最低级的I/O层。目前,只有一个驱动包括在POE的安装中-- POE::Driver::SysRW,它读写文件句柄中的数据。不管怎样,我们都不需要直接使用驱动。
Filters
    过滤器,在某个方面来说,是非常有用的。过滤器是一个简单的接口,转换数据块从一个格式成另一个格式。例如,POE::Filter::HTTPD 能够在 HTTP 1.0 requests 之间 HTTP::Request 对象互相转换。POE::Filter::Line 能够见数据流转换成序列化数据行。
Wheels
    Wheels包含了每天任务的可重复利用的高级逻辑部分。它们是POE封装有用代码的方法。在POE中你需要处理到的Wheels包括事件驱动的输入输出数据和网络连接的创建。Wheels经常使用过滤器和驱动来处理和传递数据。这个描述太过于含糊了,下面的代码将会给出一个例子来说明这个概念。
Components
    组件是一个会话,被设计来受控于其它会话。你的会话能够从它们那里来处理命令和接受事件,这点很象真实操作系统中的通过IPC通讯。一个组件的例子就是POE::Component::IRC,一个创建基于POE的IPC客户端接口,或者是POE::Component::Client::HTTP,一个事件驱动的Perl实现的HTTP用户代理。组件同样是POE非常有用的一个部分。

A Simple Example
    在这个例子中,我们会建立一个守护进程服务端,它接受TCP连接,同时打印由它的客户端提交的算术问题的答案。当有人连接它的端口31008,它将打印“Hello,client”。客户端能够提交一个算术表达式,以一个新行结束提交,服务端将送回表达式的答案。够简单吧。
    写这样一个POE程序跟写一个Unix下的守护进程的传统方法没有什么很大的不同。我们将有一个服务器会话在端口31008监听TCP连接。每当连接到来时,它将创建一个子会话来处理连接。每个子会话都能跟用户交互,然后在连接断开后安静地死掉。所有这些用Perl简单地实现只需要模块化的72行代码就行了。
    这个程序简单地以下面的代码开始:
   1  #!/usr/bin/perl -w
   2  use strict;
   3  use Socket qw(inet_ntoa);
   4  use POE qw( Wheel::SocketFactory  Wheel::ReadWrite
   5              Filter::Line          Driver::SysRW );
   6  use constant PORT => 31008;
这一段我们导入了脚本所需要的模块以及函数,并定义了监听端口的常量值。”use POE;”后面的 qw()语句一次导入了很多POE::模块。
    现在开始本文最酷的部分:
   7  new POE::Session (
   8      _start => \&server_start,
   9      _stop  => \&server_stop,
  10  );
  11  $poe_kernel->run();
  12  exit;
    这样就已经是一个完整的程序了!我建立了服务端会话,告诉POE内核开始执行事件,并且在事件结束后退出。(当没有任何会话需要管理的时候,POE内核就认为事情做完了,但是既然我们已经打算把服务端会话放在一个无穷的循环中,它将不会以这种发式退出)POE在你写"use POE;"h后,自动输出变量$poe_kernel 到你的名字空间中。
    new POE::Session 方法调用需要解释一下。当你创建一个会话时,你给内核一个这个会话将接受事件的列表。在上面的代码中,意味着这个新的会话将通过调用&server_start,&server_stop处理_start和_stop事件。任何一个受到的但没有列举到的事件,将会被会话忽略。_Start和_Stop事件对于一个POE会话来说是一个特殊事件。_start事件是当一个会话创建时第一件要做的事情,当会话将要被摧毁时内核就通知这个会话进入_stop状态。
    现在,我们已经写了完整的程序,我们还要写当会话运行时要执行的状态代码。接下来,让我们以&server_start开始。当主要的服务端会话被创建,开始执行程序时,它将会被调用。

  13  sub server_start {
  14      $_[HEAP]->{listener} = new POE::Wheel::SocketFactory
  15        ( BindPort     => PORT,
  16          Reuse        => 'yes',
  17          SuccessState => \&accept_new_client,
  18          FailureState => \&accept_failed
  19        );
  20      print "SERVER: Started listening on port ", PORT, ".\n";
  21  }

    这是一个有关POE状态的很好的例子。首先:看到变量$_[HEAP]了吗?POE有一个特殊的方法来传递参数。@_数组是由许多外部的参数打包在一起的。外部参数包括目前内核,会话和状态名的一个引用,堆栈的引用,以及其它一些东西。我们可以用POE导出的特殊常量来作为这个数组索引,比如 HEAP, SESSION, KERNEL, STATE和ARG0~ARG9(用户提供的参数)。跟POE的大部分设计一样,这样子的安排能够最大化后面的兼容性而又不牺牲速度。上面的例子存储了一个 SocketFactory wheel 在键值 listen 下。
    POE::Wheel::SocketFactory wheel是POE里最酷的东西之一。你能够用它创建任何一个流socket(UDP socket还不行),而不需要担心细节。上面的代码将创建一个SocketFactory来监听特殊的TCP端口的新连接。当连接建立时,它将调用&accept_new_client来传递一个新的客户端,如果在这其中发生错误了,它将调用&accept_failed,而不是让我们自己来处理错误。这差不多就是用POE在网络中要做的。
    我们存储一个wheel在堆栈中,以防止在状态的最后被Perl的垃圾收集机制意外地消灭掉,——这个方法在会话的每个状态中到处存在。现在我们来看&server_stop 状态的代码:

  22  sub server_stop {
  23      print "SERVER: Stopped.\n";
  24  }


这段不需要多解释了。接下来的是我们创建一个新的会话来处理每个新到的连接。

  25  sub accept_new_client {
  26      my ($socket, $peeraddr, $peerport) = @_[ARG0 .. ARG2];
  27      $peeraddr = inet_ntoa($peeraddr);
  28      new POE::Session (
  29          _start => \&child_start,
  30          _stop  => \&child_stop,
  31          main   => [ 'child_input', 'child_done', 'child_error' ],
  32          [ $socket, $peeraddr, $peerport ]
  33      );
  34      print "SERVER: Got connection from $peeraddr:$peerport.\n";
  35  }
当客户端成功地建立了跟服务端的连接后,我们的 POE::Wheel::SocketFactory将调用这个子例程。
我们将socket地址转换成人可读的IP地址,并且建立一个新的会话来跟客户端通讯。这跟前面的
POE::Session 构造器很象,但是有几点在接下来要说明。
    @_[ARG0 .. ARG2]是($_[ARG0], $_[ARG1], $_[ARG2])的快捷方式。你会在POE程序中
看到很多这样的数组切片。
    看31行:好像有点奇怪,其实这是一种很聪明的缩写。它可以用下面的比较长的方法来重写:
new POE::Session ( ... child_input => &main::child_input, child_done => &main::child_done, child_error => &main::child_error, ... );
    这是一个方便的做法来写出很多的状态名字,这些名字跟事件的名字是一样的。——你可以传递包名或者
对象来作为键,或者是任何一个有子例程,方法名组成的数组引用。可以参考POE::Session得到更多的信息。
    最后,在POE::Session 构造器参数列表最后的数组引用是我们要手动传递给_start状态的参数列表。
    如果POE::Wheel::SocketFactory在创建监听端口或者接受连接时产生了问题,下面的会发生:
36 sub accept_failed { 37 my ($function, $error) = @_[ARG0, ARG2]; 38 delete $_[HEAP]->{listener}; 39 print "SERVER: call to $function() failed: $error.\n"; 40 }

    打印错误信息是正常的处理方式,但是我们为什么还要从堆栈中删除SocketFactory wheel呢?答案在于
POE管理会话资源的方式。只要会话还能产生和接受事件,那么它就被认为是活动的。如果没有wheel,POE内核
会认为会话已经死了,并收集会话的资源。服务端得到事件的唯一方式就是从SocketFactory wheel,如果
它被消灭了,POE内核会一直等待,直到所有它的子会话结束,再收集所有占用的资源。在这一点上,既然
已经没有剩下的会话需要执行,POE内核将会结束并退出。
    所以,基本上来说,这是最通常的结束POE会话的方法:结束所有会话资源,让内核干剩下的工作。现在,
我们谈到子会话的细节。
    
  41  sub child_start {
  42      my ($heap, $socket) = @_[HEAP, ARG0];
  43      $heap->{readwrite} = new POE::Wheel::ReadWrite
  44        ( Handle => $socket,
  45          Driver => new POE::Driver::SysRW (),
  46          Filter => new POE::Filter::Line (),
  47          InputState => 'child_input',
  48          ErrorState => 'child_error',
  49        );
  50      $heap->{readwrite}->put( "Hello, client!" );
  51      $heap->{peername} = join ':', @_[ARG1, ARG2];
  52      print "CHILD: Connected to $heap->{peername}.\n";
  53  }
    每当新的子会话被创建来处理最新的连接客户端时上面的代码就会被调用。这里我们要介绍一种新的
POE wheel:ReadWrite wheel,这是一个由事件驱动的处理I/O任务的wheel。我们把它传递给文件
句柄,一个驱动,一个过滤器等等。接着,每当新的数据到达文件句柄时,wheel将发送一个child_input
事件给会话,如果有任何错误发生就会发送一个child_error 事件。
    我们理解用这个新的wheel来输出字符串”Hello,client”给socket。最后,我们存储在堆栈中
的客户端地址和端口,并打印成功信息。
    我们省略了 child_stop 的状态讨论。它只有一行长度。现在我们直接看主要的child_input 程序。
  57  sub child_input {
  58      my $data = $_[ARG0];
  59      $data =~ tr{0-9+*/()-}{}cd;
  60      return unless length $data;
  61      my $result = eval $data;
  62      chomp $@;
  63      $_[HEAP]->{readwrite}->put( $@ || $result );
  64      print "CHILD: Got input from peer: \"$data\" = $result.\n";
  65  }
    当客户端发送给我们一行数据,我们取得里面简单的算术表达式并eval它,然后把结果或者错误信息
发送给客户端。通常情况下,将客户端发送来的不可信任的数据直接就eval是非常危险的,所以我们要确保
在eval前,将字符串中所有的非数学字符全部过滤掉。子会话将一直保持接受数据直到客户端断开。
    所有事件驱动的应用都是使用POE的好地方。
源代码:http://www.perl.com/2001/01/poe-math3.pl

CONTINUE
INFO: 2008-09-01 03:33:11 | purpen | digg | link

[转载]mogileFS体系结构分析-数据库表

前面对mogileFS做了一下简单介绍,这儿开始对他进行剖析。
首先剖析他用来做文件西信息track的表结构。
使用到的数据表

  • server_settings
  • 服务器的一些配置信息,采用key=>value的记录方式保存。

  • domain
  • 域定义

  • hosts
  • 主机定义,主机的ip,存储节点服务所开的端口等信息。

  • device
  • 主机上的可用设备定义,包括设备可用空间,使用的权重等信息,由存储服务定时更新设备的情况。

  • class
  • 文件分类定义

  • file
  • 记录文件的基本信息,属于什么类别,他的key和文件大小等信息

  • tmpfile
  • 复制的临时文件信息?

  • file_to_delete
  • 记录要做删除的文件

  • file_to_delete_later
  • 要延迟删除的文件

  • file_on
  • 记录什么设备上有什么文件,一个文件在不同设备上的存储各有一条记录。

  • file_on_corrupt
  • 损坏的文件,哪一个文件在什么设备上损坏了。

  • file_to_replicate
  • 要做分发的文件,记录来源设备,失败次数和下次重试的时间等信息。

  • fsck_log
  • 文件检查日志

  • unreachable_fids
  • 不可到达的文件列表

mogileFS是一个依赖数据库做数据信息交换的系统,为了减少DB的操作次数,使用了memcached做一些查询结果的缓冲。

CONTINUE
INFO: 2008-08-19 07:57:02 | purpen | digg | link

[转载]mogileFS的工作方式(译)

原文地址: mogileFS HighLevel Overview

下面简要阐述 MogileFS 是怎么工作的.

mogileFS由如下一些部分构成:

  • Application: 想要 保存/加载 文件的应用
  • Tracker (the mogilefsd process): 基于事件的(event-based) 父 进程/消息 总线来管理所有来之于客户端应用的交互(requesting operations to be performed), 包括将请求负载平衡到 “query workers” 中,让mogilefsd的子进程去处理. 你可以在不同的机器上运行两个Tracker, 为了高可用性, 或使用更多的Tracker为了负载平衡(你需要运行多于两个的Tracker). mogilefsd的子进程有:
    • Replication — 个机器间复制文件
    • Deletion — 从命名空间删除是立即的,从文件系统删除是异步的
    • Query — 响应客户端的请求
    • Reaper — 在磁盘失败后将文件复制请求重新放到队列中
    • Monitor — 监测主机和设配的健康度和状态
  • Database — 数据库用来存放MogileFS的元数据 (命名空间, 和文件在哪里). 这应该设置一个高可用性(HA)的环境以防止单点失败.
  • Storage Nodes — 实际文件存放的地方. 存储节点是一个HTTP服务器,用来做 删除,存放等事情,任何WebDAV服务器都可以, 不过推荐使用 mogstored 。 mogilefsd 可以配置到两个机器上使用不同端口… mogstored 为所有 DAV 操作 (和流量监测), 并且你自己选择的快速的HTTP服务器用来做 GET 操作(给客户端提供文件). 典型的用户没一个加载点有一个大容量的 SATA 磁盘,他们被加载到 /var/mogdata/devNN.

High-level 流程:

  • 应用程序请求打开一个文件 (通过RPC 通知到 tracker, 找到一个可用的机器). 做一个 “create_open” 请求.
  • tracker 做一些负载均衡(load balancing)处理,决定应该去哪儿,然后给应用程序一些可能用的位置。
  • 应用程序写到其中的一个位置去 (如果写失败,他会重新尝试并写到另外一个位置去).
  • 应用程序 (client) 通过”create_close” 告诉tracker文件写到哪里去了.
  • tracker 将该名称和域命的名空间关联 (通过数据库来做的)
  • tracker, 在后台, 开始复制文件,知道他满足该文件类别设定的复制规则
  • 然后,应用程序通过 “get_paths” 请求 domain+key (key == “filename”) 文件, tracker基于每一位置的I/O繁忙情况回复(在内部经过 database/memcache/etc 等的一些抉择处理), 该文件可用的完整 URLs地址列表.
  • 应用程序然后按顺序尝试这些URL地址. (tracker’持续监测主机和设备的状态,因此不会返回死连接,默认情况下他对返回列表中的第一个元素做双重检查,除非你不要他这么做..)
CONTINUE
INFO: 2008-08-19 07:45:15 | purpen | digg | link

[转载]mogilefs分布式文件系统

MogileFS是一套高效的文件自动备份组件,由Six Apart开发,广泛应用在包括LiveJournal等web2.0站点上。

MogileFS由3个部分组成:
第1个部分是server端,包括mogilefsd和mogstored两个程序。前者即是mogilefsd的tracker,它将一些全局信息保存 在数据库里,例如站点domain,class,host等。后者即是存储节点(store node),它其实是个HTTP Daemon,默认侦听在7500端口,接受客户端的文件备份请求。在安装完后,要运行mogadm工具将所有的store node注册到mogilefsd的数据库里,mogilefsd会对这些节点进行管理和监控。
第2个部分是utils(工具集),主要是MogileFS的一些管理工具,例如mogadm等。
第3个部分是客户端API,目前只有Perl API(MogileFS.pm),用这个模块可以编写客户端程序,实现文件的备份管理功能。☆
提供MogileFS.pm

CONTINUE
INFO: 2008-08-12 06:14:06 | purpen | digg | link

[转载]跑步机减脂全攻略

      如今,跑步机已经成为世界上最受欢迎的室内健身器械,1987年,全球有440万跑步机锻炼者,今天仅在美国就有4300万使用者,增长率为惊人的近10倍!

这个天文数字的增长自有它的理由。跑步机变得噪音越来越小,并且使用简单。电脑控制的反馈功能包括心率、热量消耗、速度、速率,还有坡度。许多型号的产品设有预定的运动模式,甚至还有根据练习者的心率变化而自动改变速度与坡度的功能。当然,跑步机受到宠爱的最主要原因还是它在改善体能方面的高效率。

科学研究证 明,跑步机比其他任何有氧运动器械消耗的热量更多。一项在美国威斯康星州医学院进行的研究对跑步机、台阶机、固定自行车、越野滑雪机与划船机的效果进行了 比较。参与者以不同运动强度在不同器械上运动,结果发现,在高强度情况下跑步机是绝对的赢家,1小时能消耗850千卡热量,台阶机与划船趴列第二,第小时 700千卡。在低强度运动时,跑步机仍然是冠军,每小时消耗550千卡,而台阶机的消耗量是500千卡。

跑步机在提高耐力、消耗热量及减少体脂方面效果最为出色。但这些还不是它的惟一用途。跑步机对下肢和上肢的塑形都有很大帮助。以下介绍如何有效地使用跑步机以达到上述目的,重点集中在消耗体脂与热量方面。

1、减脂运动区

如何充分利用跑步机来达到健身减肥的 目的呢?减肥实际上就是一个热量消耗大于热量摄入的公式。如果你能实现负平衡,体脂就会减少。你一定听说过“减脂运动区”的说法,也就是说在最高心率的 65-70%进行有氧运动是最合适的减肥运动强度。这个理论的根据十分简单,在中、低强度运动时,身体能够向工作肌肉提供足够的氧气来进行有氧能量代谢, 而且肌肉在此条件下也能够最大化地利用贮存脂肪作 为热量来源消耗在运动过程中。相反,在高强度运动时,身体不能及时向工作肌肉提供足够的氧气来支持其代谢过程,于是热量在缺氧状态下被分解利用。这时消耗 的主要是碳水化合物,脂肪只占很小一部分。当然,在任何情况下,身体都不会单纯消耗脂肪或碳水化合物,从有氧代谢到无氧代谢有一个转化的过程。因此,如果 你的运动目的是消耗脂肪,这个“减脂运动区”似乎是很有道理的。

但是,如果我们进一步探究热量消耗的问题时会发现,虽然在低强度运动时消耗的脂肪比例较高,但是热量消耗的来源并不对长期减肥的效果产生重要影 响。记住,减肥是一个热量摄入与消耗的平衡问题。低强度运动时消耗的脂肪比例虽然较高,但是高强度运动所消耗的实际脂肪量可能更高,因为总消耗热量被提高 了。

因此,你应该把尽可能地增加单次运动的热量消耗放在第一位,这是实现持续的体内热量负平衡的关键。一项研究比较了两组18~34岁女性的减肥效果。其中一组人用高强度运动,另一组用低强度,两组人的饮食相同。11个星期后,高强度运动组显示出明显的体脂水平下降,而低强度组则没有发生体脂的变化。

高强度运动除了能消耗更多的热量以外,它对身体代谢率的提高效果在运动结束后还会持续一段时间,从而进一步促进了减脂效果。

2、减脂运动方法

由于高强度有氧运动是减肥与防止反弹的最佳方式,那么是否应该在运动中尽可能长时间地保持高强度呢?遗憾的是,虽然那样做可能在单位时间中最大程度地消耗了热量与脂肪,但是身体不可能坚持足够长的时间。因此把短时间的高强度运动与低强度的恢复交替进行是最可行的办法。

如何知道自己的运动强度呢?有两个常用的方法来确认运动强度。第一是用心率来衡量,第二是用“自我评定强度等级”(RPE)来判断。心率测定需 要佩戴一个心率监测器,然后用“220-年龄”的公式预算出你的目标心率。比如,一个35岁的人想采用65%的强度运动,那么计算方法就是(220- 35)×0.65=120。

虽然这个方法被广泛应用,但它有许多缺陷。最大的问题是“220-年龄”得出的最高心率不精确,每个人的实际最高心率会因为体质不同,而高于或 低于这个计算结果。除此以外,运动当天的身体状况,甚至天气,都会影响到心率。相比之下,RPE应该更实用与准确一些。RPE把运动强度分成1~20个不 同等级,1是不做任何努力,20是极度努力。在运动中你根据自己的感觉来做出判断。我们把在跑步机上锻炼的强度简单地分成以下3个档次:

一级——RPE 12~13,较容易,相当于65%心率,

二级——RPE 15~16,有难度,相当于80%心率。

三级——RPE 17~18,非常难,相当于90%心率。

当你在“一级”强度跑步时,应该可以边运动边清楚地说话,但不能唱歌。在“二级”强度时说话有些费力,但努力程度不能太高。你应该能够坚持运动20分钟以上。“三级”强度接近极度努力,只能坚持5~10分钟。

“一级”运动的目的是增强耐力,从高强度运动中恢复体力。“二级”运动,的一个重要目的是提高“乳酸耐受界”。肌肉在此强度下运动时,会在消耗 热量的同时产生许多副产品——乳酸。乳酸经过一系列化学反应可以再次转化为热量供肌肉使用,但是当乳酸的产生速度超过了转化速度而出现堆积,肌肉会迅速疲劳, 被迫降低运动强度直到停止。“二级”强度运动能够提高人体处理乳酸的能力,使你得以保持更长时间的高强度运动.“乳酸耐受界”提高后,曾令人感觉非常吃力 的运动强度会变得比较容易坚持了,你也会消耗掉更多热量与脂肪,“三级”运动强度也能促进这个过程,并改善下肢肌肉,包括臀肌、股二头肌与小腿肌的外形。

跑步机对减肥是种非常理想的运动器械,你能够准确地把握速度,坡度及时间,不管你是一个新手还是资深运动员,都能够根据自己的运动目的特别设计一套锻炼计划。以下是一个把三种运动强度结合在一起,以减肥为目标的周计划。

第一天:小运动量低强度

把跑步机坡度调到1%,强度“一级”,慢跑或快走40~60分钟。你不可能每天都进行高强度锻炼,肌肉需要调整恢复,以便更好地完成任务。

第二天:变速练习

把坡度上升到1%,跑或快走30~60分钟。每5分钟换一次强度,“一级”与“三级”交替进行。随着体能的加强,“三级”的时间也应该相应加长。这意味着持续提高身体的消耗热量能力。

第三天:休息或放松练习

你可以完全休息或练习第一天的内容。

第四天:“乳酸耐受界”练习

把跑步机坡度上升到1%,热身后以“二级”强度跑或快走20分钟。开始阶段你也许只能完成一次20分钟练习,随着体能增强,你会完成2次甚至3次20分钟的强度练习。两次之间慢跑5分钟恢复。

第五天:休息或放松练习(同第一天)

第六天:坡度练习

把跑步机坡度定在4%,用“二级”强度跑或快走1分钟。然后把坡度下降到2%,用“一级”强度跑或快走1分钟。再次提高坡度到5%,用“二级” 强度跑或走5分钟,之后下降到2%,放松1分钟。这样循环直到你达到坡度10%,最后以坡度2%放松5分钟结束。当你的体能得到提高.需要增加强度时,用 加快速度而不是坡度来实现。这个练习对加强下肢力量非常有效.也能改善下肢肌肉的线条。

第七天:休息

无论你的有氧健身目标是什么,使用跑步机都会有所帮助.合理利用这种绝妙的健身工具,你一定能够达到自己的目的。

减少患心脏病的危险

高强度运动不但能提高脂肪消耗能量与体能水平,而且还会降低患心脏病的危险。日本的一项有关长寿的研究证实,高强度的跑步比低强度的步行更能减少患冠心病的危险。

计算热量消耗

大多数跑步机都能显示热量消耗,但是这个数字通常不够准确。以下是一个简便的计算方法。如果你在“一级”强度运动,每分钟大约消耗3~5千卡热 量。中等强度每分钟消耗10千卡,而高强度则消耗15千卡热量。当然,锻炼者的体重因素也应该考虑在内。体重越大,消耗量越多。

CONTINUE
INFO: 2008-08-12 02:00:54 | purpen | digg | link

[转载]如何正确使用跑步机

很多人都选择跑步机来锻炼,可是你认真考虑过为什么要选择跑步机锻炼吗?请认真地阅读这份跑步机的“说明书”!

一般情况下,人们选择跑步机主要有几个目的,减肥、提高心肺功能、放松、康复等,但是每种目的在跑步机上都有不同的体现。

减肥:时间30~40分钟

因为消耗体内脂肪要在中等强度运动半小时到四十五分钟后才开始,所以,利用跑步机减肥一定要控制好时间和速度。最好将时间设定为30~40分钟,如 果还要进行其他运动,可以减少时间但最好不要低于20分钟,而速度的设定因性别不同存在差异,男的最好在6.5~8.5之间,而女的则最好在 5.5~7.5之间。而且要注意跑步时手臂的摆动,不要扶在扶手上,因为这样可以消耗更多的能量,也更自然安全。

练心肺:速度5~9坡度0%~10%

如果决定要练习自己的心脏,那么最好先去咨询一下运动医学专家。根据他的建议为自己设定目标心率,一般来说,当你在跑步时达到目标心率后,要维持 25~35分钟,而速度最好设定在5~9之间,坡度控制在0%~10%之间。当你完成整个运动后不要急着下来,最好把速度降下来再跑5分钟左后,做好恢复 工作。

热身:时间5~10分钟速度别超过8

如果你想利用跑步机进行热身或放松,时间控制在5~10分钟即可,而速度也最好不要超过8,尤其是在进行准备活动的时候最好循序先用4.5~6的速 度跑 3~5分钟,接着用8~10的速度跑2~3分钟,再降到5~7的速度跑3~5分钟。这样可以避免体力的不必要消耗。坡度用0%~4%就可以。

CONTINUE
INFO: 2008-08-12 01:59:39 | purpen | digg | link

[转载]PERL进程、管道、信号

PERL灵活的进程函数是为了复制进程用于分担任务与程序的工作量。

PERL中复制进程有两种方法:fork()、system()与exec()。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

fork()部分:*NIX传统的复制进程方法

==============================================================

fork()函数:

作用:进程复制函数。

用法:$pid=fork();

讲解:

无参数;当本进程为父进程时返回值为子进程的PID值,当进程为子进程时返回值为0。

实例:

#!usr/bin/perl -w

$pid=fork(); #复制进程,并把返回值附入$pid

die "Error:$!\n" unless defined $pid; #制定程序的错误机制,此步可略

if($pid!=0){ #条件选择,测试$pid值

print"This is a main pid!PID is $$!\n"; #$pid值不等于0,此为父进程(附:$$为保留变量,其值为此进程的PID)

}else{ #否则.....

print"This is a sub pid!PID is $$!\n"; #$pid值为0,此为子进程

}

exit 1; #退出程序

分析实例:

楼上的程序没有父进程与子进程的明显分化,要将它们分开就要靠测试$pid的值,所以对fork()函数的调用来说条件语句是非常重要的,需要通过它们来辨别fork() 的返回值。

±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

getppid()函数:

作用:在子进程中调用此函数来获得父进程PID值。

用法:$parent=getppid();

讲解:无参数,调用后其返回值为父进程的PID值。

实例:

#!usr/bin/perl -w

$pid=fork(); #复制进程

die "Error:$!\n" unless defined $pid; #制定错误机制,此步可略

if($pid==0){ #当进程为子进程则进入条件,当进程为父进程则跳过到程序结束

$parent=getppid(); #通过getppid()得到父进程PID值

print"This is a sub pid:$$,the parent is $parent\n"; #在STDOUT打印子进程PID值与其父进程ID值

}

exit 1; #退出程序

注意:楼上的getppid()实例无法在WIN32下通过,建议使用*nix平台。

±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

关于使用fork():通过fork()创建的子进程共享了父进程的所有变量、句柄等当前值。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

system()与exec()部分:更直观的进程调用

=============================================================

system()函数:

作用:直接生成子进程。

用法:$result=system("dir/w *.bat"); 或 $result=system("dir/w","*.bat");

讲解:参数为SHELL语句。当函数能正常调用时返回值为0(注意:此与其他函数不一致),其他返回值均为错误。

实例:

#!usr/bin/perl -w

print STDOUT system("dir/w","*.pl"); #把system()函数中的子进程SHELL语句"dir/w *.pl"的结果输出到STDOUT中

exit 1; #退出程序

#在c:\根目录下运行结果为:

C:\>perl mm.pl

驱动器 C 中的卷没有标签。

卷的序列号是 2629-08EF

C:\ 的目录

aaa.pl bbb.pl zzz.pl xxx.pl SOCK.PL

connect.pl connect2.pl connect3.pl connect4.pl connect5.pl

connect6.pl connect7.pl udpc.pl udps.pl connect8.pl

connect10.pl fork.pl pidd.pl mm.pl

19 个文件 7,503 字节

0 个目录 5,514,014,720 可用字节

0

#注意楼上最后的"0",这就是返回后的数值,楼上表示程序正常调用了system()函数中的shell语句了。  

±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

exec()函数:

作用:以指定的SHELL语句代替原进程。

用法:$result=exec("copy *.bat c:\"); 或 $result=exec("copy","*.bat","c:\");

讲解:参数为SHELL语句,成功调用后返回值为undef,其他返回值均为失败。使用此函数后生成的新进程与原进程为同一进程,

有相同的PID,共享变量语柄等一切当前值。

实例与system()相当,所以不作讨论了。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

附:关于"Perl的管道"部分内容博大精深,而本人又水平有限,所以只好草草了事,如果有哪里不妥还望各位前辈指点

管道是为了使不同进程可以进行通信的制定的。管道是*NIX编程的重点。

与其相关的函数有:open()、pipe()等等。

open():作打开句柄用。

格式:open(FILEHANDLE,"符号+参数");

例子:open(NIX,"|wc -lw"); #打开名为NIX的管道,其进程为‘wc -lw’,管道为写入。

open(DDD,"dir c:\|"); #打开名为DDD的管道,其进程为‘dir c:\’,管道为读取。

讲解:FILEHANDLE(句柄)包括很多成分,如文件句柄、SOCKET句柄、管道句柄,此文只谈到管道句柄。

第二个参数为双引号或单引号相括着的管道符号与参数。管道符号为"|",把管道符号放到参数的左边为‘只读’,放到右边为‘只写’,如果两边都有便为双向管道(既可读也可写)。

简单的管道实例:

#!usr/bin/perl -w

open(AAA,"dir d:|"); #打开管道AAA,进程为"dir d:",只读

@bbb=<AAA>; #从管道中读取内容,并压入@bbb数组

print"@bbb\n"; #把@bbb数组全部输出到STDOUT

close AAA; #关闭管道AAA

exit 1; #退出程序

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓

pipe():创建管道对。

格式: pipe(READ,WRITE);

实例:pipe(README,WRITEME); #创建了一个管道对,"README"用于读,"WRITEME"用于写。

$aaa=pipe(AAA,BBB); #创建了一个管道对,"AAA"用于读,"BBB"用于写,$aaa变量为调用pipe()的返回值。

讲解:正常调用后返回值为非零数,第一个参数为被创建的读管道,第二个参数为被创建的写管道。此函数通常配合进程中

的fork()函数一同使用,步骤是先使用pipe()函数建立管道对,再使用fork()创建新进程,在不同的进程关闭不同的

管道,这样就可以达到管道间通信的目的了。

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓

close():关闭管道

格式: close(AAA);

close BBB;

实例与格式相当,也就不详细介绍了。

讲解:close()在调用时能将子程序的终止代码放到特殊变量$?中;当关闭的是写管道时close()调用将进入堵塞状态直至另一

端完成它的全部工作为止。

信号其实就是编程里俗称的中断,它使监视与控制其他进程变为有可能。

首先说说通用信号,通用信号归纳起来可以组成以下列表:

=============================================================

信号名 值 标注 解释

------------------------------------------------------------------------

HUP 1 A 检测到挂起

INT 2 A 来自键盘的中断

QUIT 3 A 来自键盘的停止

ILL 4 A 非法指令

ABRT 6 C 失败

FPE 8 C 浮点异常

KILL 9 AF 终端信号

USR1 10 A 用户定义的信号1

SEGV 11 C 非法内存访问

USR2 12 A 用户定义的信号2

PIPE 13 A 写往没有读取者的管道

ALRM 14 A 来自闹钟的定时器信号

TERM 15 A 终端信号

CHLD 17 B 子进程终止

CONT 18 E 如果被停止则继续

STOP 19 DF 停止进程

TSTP 20 D tty键入的停止命令

TTIN 21 D 对后台进程的tty输入

TTOU 22 D 对后台进程的tty输出

------------------------------------------------------------------------

著明:上表中‘值’列下没有列出的值所对应的信号为系统调用的非标准信号,在此

文不予以探讨。上表中的第三列‘标注’定义了当进程接受到信号后的操作,

如:

A-----终止进程

B-----忽略进程信号

C-----终止进程并卸下内核

D-----停止进程

E-----恢复进程

F-----不能截取或忽略进程信号

=============================================================

下面就以INT作范例演示一下调用过程吧:

#!usr/bin/perl -w

#c:\test11.pl

my $aaa=0; #对计数器变量$aaa进行负值

while($aaa<3){ #进入循环体

print"Begin\n"; #打印字符串到STDOUT

sleep(5); #睡眠函数,参数为5秒

next unless $SIG{INT}=\&demon; #选择结构,demon子程序值负于中断函数

}

sub demon{ #demon子程序体

$aaa++; #计数器自加

print"Stop!\n"; #打印字符串到STDOUT

}

exit 1; #退出程序

输出结果:在SHELL里不停的打印出"Begin"字样,相隔5秒,一但在键盘中执行程序

中断操作(Control+"c"),屏幕就会打印出"Stop!"字样,不停地继续下去。

中断调用总结:调用需要使用到系统保留全局HASH数组%SIG,即使用"$SIG{信号名}"

截取信号,截取后将其负某个代码(子函数)的地址值,这代码就是截

取后要执行的结果了。

CONTINUE
INFO: 2008-07-30 09:40:29 | purpen | digg | link

Copyright © 2008 Jaever. All rights reserved.

This Site looks and works best when viewed using browsers enabled with JavaScript 1.5 and CSS, such as Firefox 1+ or Safari 3+.