+ -
当前位置:首页 → 问答吧 → 请教这个POE程序的执行流程

请教这个POE程序的执行流程

时间:2011-02-14

来源:互联网

POE::Session->create(
      inline_states => {
         _start => sub {
            my ($heap) = $_[HEAP];
            my $log_watcher  = POE::Wheel::FollowTail->new(
                Filename     => "my_log_file.txt",
                InputEvent   => "redirect",
            );
            my $dumper = POE::Wheel::Run->new(
                Program      => "/usr/bin/hexdump",
                StdoutEvent  => "print"
            );

            $heap->{watcher} = $log_watcher;
            $heap->{dumper}  = $dumper;
         },
         redirect => sub {
            my ($heap, $data) = @_[HEAP, ARG0];
            $heap->{dumper}->put($data);
         },

         print => sub { my $record = $_[ARG0]; print $record, "\n"; }
      }
    );

从Perl高级编程第二版上看到的例子, 但是不太理解这个流程。我感觉是不是这样
1. 程序run起来后,往my_log_file.txt 写入新的一行, POE::Wheel::FollowTail会响应InputEvent这个事件,从而执行"redirect“ 方法,在这个方法里调用了POE::Wheel::Run的put方法。
2. POE::Wheel::Run的put方法是怎么触发POE::Wheel::Run的StdoutEvent事件的呢?
3. /usr/bin/hexdump又是在何时被调用的呢?

作者: niannian   发布时间: 2011-02-14

本帖最后由 flw 于 2011-02-14 16:26 编辑

这段代码创建了一个 POE Session,这个 Session 在启动的时候,派生了两个 Wheel。

其中一个是 FollowTail,这个 Wheel 可以像 tail -f 一样读取 my_log_file.txt 的增量变化。
由 FollowTail 的文档可知每当有变化时会触发 InputEvent 参数指定的事件,也就是 redirect 事件。

redirect 事件把变化的内容通过 $_[ ARG0 ] 拿到以后,又 put 给了 Run 这个 Wheel。
说起 Run 这个 Wheel 要额外交代一句,它会在创建的时候(new 的时候)就派生出一个子进程,这个子进程的可执行文件在本例中由 Program 参数指定。

这个 Wheel 在被 put 了数据的时候,会通过管道把 put 的内容写入到这个子进程的 STDIN 里面去,
而 hexdump 这个程序的特点就是不断地从 STDIN 读取内容,并打印到 STDOUT。

根据 POE::Wheel::Run 的文档可知,子进程的 STDOUT 有输出时,会触发 StdoutEvent 参数所指定的事件,
所以当你 put 了数据进去之后,就会收到一个 print 事件。
这个事件的参数($_[ARG0])也就是你 put 进去的数据经过了 hexdump 翻译之后得到的内容。

作者: flw   发布时间: 2011-02-14

擦。。。有幸得到flw大版主这么详尽的解答。。。明白了。。不胜感激。。。

作者: niannian   发布时间: 2011-02-14

再多问一句,我看很多wheel都有put这个方法,是不是每个wheel的put方法都是把数据写到子进程的STDIN里面去呢?

作者: niannian   发布时间: 2011-02-14

看了一下CPAN上很多wheel的文档,基本上都是这样的解释:
put RECORDS

put() queues up a list of RECORDS that will be sent to the child process' STDIN filehandle. These records will first be serialized according to the wheel's StdinFilter. The serialized RECORDS will be flushed asynchronously once the current event handler returns.

看来都应该是写到STDIN了

作者: niannian   发布时间: 2011-02-14