perl多任务问题

时间:2010-06-18 01:04:03

标签: perl multithreading parallel-processing multitasking

我已经完成了我之前使用perl线程的多线程程序,它可以在我的系统上运行。问题是,在某些需要运行的系统上,线程支持不会编译到perl中,我无法安装其他软件包。因此,我需要使用除线程之外的其他东西,我正在将代码移动到使用fork()。这可以在我的Windows系统上启动子任务。

一些问题:

  1. 如何确定子进程何时退出?我在线程数低于某个值时创建了新线程,我需要跟踪正在运行的线程数。对于进程,我如何知道何时退出,以便我可以跟踪当时有多少存在,在创建一个计数器时递增计数器并在退出时递减计数器?

  2. 在子进程中父进程安全打开时,是否使用OPEN获取的句柄的文件I / O?我需要为每个子进程追加一个文件,这在unix上也是安全的。

  3. fork和thread有什么替代方法吗?我尝试使用Parallel :: ForkManager,但是我的系统上没有安装它(使用Parallel :: ForkManager;出错)我绝对要求我的perl脚本可以在所有unix / windows系统上运行而无需安装任何其他模块。 / p>

2 个答案:

答案 0 :(得分:6)

典型用法:

use POSIX ':sys_wait_h';    # for &WNOHANG

# how to create a new background process
$pid = fork();
if (!defined $pid) { die "fork() failed!" }
if ($pid == 0) { # child
    # ... do stuff in background ...
    exit 0;      # don't forget to exit or die from the child process
} 
# else this is the parent, $pid contains process id of child process
# ... do stuff in foreground ...

# how to tell if a process is finished
# also see  perldoc perlipc
$pid = waitpid -1, 0;           # blocking wait for any process
$pid = wait;                    # blocking wait for any process
$pid = waitpid $mypid, 0;       # blocking wait for process $mypid
# after blocking wait/waitpid
if ($pid == -1) {
    print "All child processes are finished.\n";
} else {
    print "Process $pid is finished.\n";
    print "The exit status of process $pid was $?\n";
}

$pid = waitpid -1, &WNOHANG;    # non-blocking wait for any process
$pid = waitpid $mypid, 0;       # blocking wait for process $mypid
if ($pid == -1) {
    print "No child processes have finished since last wait/waitpid call.\n";
} else {
    print "Process $pid is finished.\n";
    print "The exit status of process $pid was $?\n";
}

# terminating a process - see  perldoc -f kill  or  perldoc perlipc
# this can be flaky on Windows
kill 'INT', $pid;               # send SIGINT to process $pid

perldoc -f forkwaitpidwaitkillperlipc中的Gory详细信息。 perlipc中关于为SIGCHLD事件设置处理程序的内容应该特别有用,尽管在Windows上不支持。

分叉进程的I / O在Unix和Windows上通常是安全的。文件描述符是共享的,所以对于像这样的东西

open X, ">", $file;
if (fork() == 0) {  # in child
    print X "Child\n"; 
    close X;
    exit 0;
}
# in parent
sleep 1;
print X "Parent\n";
close X;

子进程和父进程都会成功写入同一个文件(但要注意输出缓冲)。

答案 1 :(得分:3)

看看waitpid。这里有一些代码需要完成9个任务(1到9)。它将启动三名工人来完成这些任务。

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";

my $max_children = 3;
my %work = map { $_ => 1 } 1 .. 9;
my @work = keys %work;

my %pids;
while (%work) {
    #while there are still empty slots
    while (@work and keys %pids < $max_children) {
        #get some work for the child to do
        my $work = shift @work;

        die "could not fork" unless defined(my $pid = fork);

        #parent
        if ($pid) {
            $pids{$pid} = 1;
            next;
        }

        #child
        print "$$ doing work $work\n";
        sleep 1;
        print "$$ done doing work $work";
        exit $work;
    }

    my $pid = waitpid -1, WNOHANG;

    if ($pid > 0) {
        delete $pids{$pid};
        my $rc = $? >> 8; #get the exit status
        print "saw $pid was done with $rc\n";
        delete $work{$rc};
        print "work left: ", join(", ", sort keys %work), "\n";
    }

    select undef, undef, undef, .25;
}