【问题标题】:perl multiple tasks problemperl 多任务问题
【发布时间】:2011-03-05 05:50:00
【问题描述】:

我已经完成了我早期的使用 perl 线程的多线程程序,它可以在我的系统上运行。问题是在一些需要运行的系统上,线程支持没有编译到 perl 中,我无法安装额外的包。因此,我需要使用线程以外的东西,并且我正在将我的代码移动到使用 fork()。这适用于我的 Windows 系统启动子任务。

几个问题:

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

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

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

【问题讨论】:

  • 更像是一种解决方法,但也许您可以在进程启动时写入文件,然后在退出时删除文件或类似的东西......拥有一个主脚本来监视这些文件左右...... .

标签: perl multithreading parallel-processing multitasking


【解决方案1】:

典型用法:

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 中的血腥细节。 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;

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

【讨论】:

    【解决方案2】:

    看看waitpid。这里有一些代码需要完成九个任务(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;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多