perl多任务问题

perl多任务问题,perl,multithreading,parallel-processing,multitasking,Perl,Multithreading,Parallel Processing,Multitasking,我已经完成了我以前使用perl线程的多线程程序,它可以在我的系统上运行。问题是,在某些需要运行线程的系统上,线程支持没有编译成perl,我无法安装其他软件包。因此,我需要使用线程以外的东西,我正在将代码移到使用fork()。这在我的windows系统上可以启动子任务 有几个问题: 如何确定子进程何时退出?当线程数低于某个值时,我创建了新线程,我需要跟踪有多少线程正在运行。对于进程,我如何知道一个何时退出,以便跟踪当时存在多少个进程,在创建一个进程时递增计数器,在退出时递减计数器 当父进程在子进程

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

有几个问题:

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

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

  • 除了叉子和线还有别的选择吗?我尝试使用Parallel::ForkManager,但我的系统上没有安装它(使用Parallel::ForkManager;给出了一个错误),我绝对要求我的perl脚本在所有unix/windows系统上工作,而不安装任何其他模块

  • 看一看。下面是一些代码,其中有九个任务需要完成(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;
    }
    
    #/usr/bin/perl
    严格使用;
    使用警告;
    使用POSIX“:sys_wait_h”;
    我的$max_children=3;
    我的%work=map{$\=>1}1。。9;
    我的@work=键%work;
    我的%pids;
    同时(工作百分比){
    #当仍有空插槽时
    while(@work and key%pids<$max_children){
    #给孩子找些工作做
    我的$work=shift@work;
    除非定义(my$pid=fork),否则die“无法分叉”;
    #母公司
    如果($pid){
    $pid{$pid}=1;
    下一个
    }
    #孩子
    打印“$$doing work$work\n”;
    睡眠1;
    打印“$$done doing work$work”;
    退出$work;
    }
    my$pid=waitpid-1,WNOHANG;
    如果($pid>0){
    删除$pid{$pid};
    my$rc=$?>>8;#获取退出状态
    打印“saw$pid是用$rc完成的\n”;
    删除$work{$rc};
    打印“剩余工时:”,连接(“,”,排序键%work),“\n”;
    }
    选择未定义、未定义、未定义、.25;
    }
    
    典型用法:

    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
    
    血淋淋的细节在、、和中。
    perlipc
    中关于为
    SIGCHLD
    事件设置处理程序的内容应该特别有用,尽管Windows不支持

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

    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;
    

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

    更像是一种解决方法,但您可以在进程启动时写入文件,然后在退出时删除该文件或类似的内容。。。有一个主脚本来监视这些文件等等。。。