perl多任务问题

发布于 2024-09-06 06:27:08 字数 574 浏览 5 评论 0原文

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

几个问题:

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

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

  3. 除了 fork 和 thread 之外还有其他选择吗?我尝试使用 Parallel::ForkManager,但它没有安装在我的系统上(使用 Parallel::ForkManager;给出了错误),并且我绝对要求我的 perl 脚本在所有 unix/windows 系统上工作,而无需安装任何其他模块。< /p>

I have finished my earlier multithreaded program that uses perl threads and it works on my system. The problem is that on some systems that it needs to run on, thread support is not compiled into perl and I cannot install additional packages. I therefore need to use something other than threads, and I am moving my code to using fork(). This works on my windows system in starting the subtasks.

A few problems:

  1. How to determine when the child process exits? I created new threads when the thread count was below a certain value, I need to keep track of how many threads are running. For processes, how do I know when one exits so I can keep track of how many exist at the time, incrementing a counter when one is created and decrementing when one exits?

  2. Is file I/O using handles obtained with OPEN when opened by the parent process safe in the child process? I need to append to a file for each of the child processes, is this safe on unix as well.

  3. Is there any alternative to fork and threads? I tried use Parallel::ForkManager, but that isn't installed on my system (use Parallel::ForkManager; gave an error) and I absolutely require that my perl script work on all unix/windows systems without installing any additional modules.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你如我软肋 2024-09-13 06:27:08

典型用法:

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 fork 中的详细信息, waitpid等待killperlipcperlipc 中有关为 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;

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

Typical usage:

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

Gory details in perldoc -f fork, waitpid, wait, kill, and perlipc. The stuff in perlipc about setting up a handler for SIGCHLD events should be particularly helpful, though that isn't supported on Windows.

I/O across forked processes is generally safe on Unix and Windows. File descriptors are shared, so for something like this

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;

both child and parent processes will successfully write to the same file (be aware of output buffering, though).

我是有多爱你 2024-09-13 06:27:08

看一下 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;
}

Take a look at waitpid. Here is some code that has nine tasks that need to be done (1 through 9). It will start up to three workers to do those tasks.

#!/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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文