use*_*035 4 optimization perl waitpid
以下代码运行2个孩子,他们将等待10秒并终止.父母坐在一个循环中,等待孩子们终止:
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
sub func
# {{{
{
my $i = shift;
print "$i started\n";
$| = 1;
sleep(10);
print "$i finished\n";
}
# }}}
my $n = 2;
my @children_pids;
for (my $i = 0; $i < $n; $i++) {
if ((my $pid = fork()) == 0) {
func($i);
exit(0);
} else {
$children_pids[$i] = $pid;
}
}
my $stillWaiting;
do {
$stillWaiting = 0;
for (my $i = 0; $i < $n; ++$i) {
if ($children_pids[$i] > 0)
{
if (waitpid($children_pids[$i], WNOHANG) != 0) {
# Child is done
print "child done\n";
$children_pids[$i] = 0;
} else {
# Still waiting on this child
#print "waiting\n";
$stillWaiting = 1;
}
}
#Give up timeslice and prevent hard loop: this may not work on all flavors of Unix
sleep(0);
}
} while ($stillWaiting);
print "parent finished\n";
Run Code Online (Sandbox Code Playgroud)
代码基于这个答案:多个fork()并发
它工作正常,但父循环正在吃处理器时间.top命令给出:

这里的回答说:
作为额外的奖励,循环将在
waitpid孩子们运行时阻止,因此您在等待时不需要繁忙的循环.
但对我来说它并没有阻止.怎么了?
你正在传递WNOHANG旗帜,这使得呼叫无阻塞.删除此标志并waitpid等待0%CPU,直到孩子退出.
如果采用这种方法,则可以简化代码.在子项完成之前无需循环,因为阻塞waitpid调用将为您执行此操作:
for (my $i = 0; $i < $n; ++$i) {
if ($children_pids[$i] > 0) {
waitpid($children_pids[$i], 0);
print "child done\n";
$children_pids[$i] = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
或者,将sleep呼叫更改为等待一秒钟.然后,您的程序将每秒检查已完成的子项,而不会提高CPU使用率.
| 归档时间: |
|
| 查看次数: |
7703 次 |
| 最近记录: |