- 论坛徽章:
- 0
|
本帖最后由 honckly 于 2010-03-21 15:25 编辑
刚开始学习perl,最近工作中遇到一个问题,请高人耐心看完,给提出一个解决方案,小弟感激不尽
场景:需要对一个目录的所有文件的内容进行处理,如果单个处理的话,耗时较大,所以采用fork()形式
代码:由于刚学习perl编程,所以用的他人的代码块,有些地方看不太懂
这里设置最大进程数为$MAX_PID = 20,@tables里有2百个文件,也就是说循环200次
foreach (my $i=0; $i<@tables; $i++) {
if ($pid_num < $MAX_PID) {
$pid=fork();
if (defined $pid) {
if ($pid!=0) {
# 父进程
$pid_hash->{$i}->{pid} = $pid;
$pid_hash->{$i}->{table} = $tables[$i];
$pid_hash->{$i}->{starttime} = TimeOpt::CFtime("YYYY-MM-DD hh:mm:ss");
}
}
else {
# fork失败
$TRACE->trace("Cann't fork $!");
next;
}
if ($pid==0) {
# 子进程
$table = $tables[$i];
eval{
&get_file_content($table, $i);
};
exit(0);
}
else {
# 父进程
$pid_num++;
next;
}
}
else {
$i--;
while (1) {
$TRACE->trace("Running pid num = $pid_num");
my $tag=0;
my $pid;
foreach my $itmp (keys %$pid_hash) {
$pid = $pid_hash->{$itmp}->{pid};
if ($pid!=0) {
if (!(Fcommon::isProcAlive($pid))) {
$TRACE->trace("Run Finish pid=".$pid_hash->{$itmp}->{pid}." table=".$pid_hash->{$itmp}->{table});
$pid_hash->{$itmp}->{pid} = 0;
$pid_num--;
$tag = 1;
}
else {
my $timeout_time = TimeOpt::GMtime($pid_hash->{$itmp}->{starttime},"+5s");
my $current = TimeOpt::CFtime("YYYY-MM-DD hh:mm:ss");
if ($current ge $timeout_time) {
system("kill -p $pid");
$pid_hash->{$itmp}->{pid}=0;
$pid_num--;
$tag = 1;
}
}
}
}
if ($tag==1) {
last;
}
sleep 2;
}
}
}
#守护程序
while (1) {
my $tag = 0;
my $pid;
foreach my $itmp (keys %$pid_hash) {
$pid = $pid_hash->{$itmp}->{pid};
if ($pid!=0) {
if (Fcommon::isProcAlive($pid)) {
my $timeout_time=TimeOpt::GMtime($pid_hash->{$itmp}->{starttime},"+5s");
my $current=TimeOpt::CFtime("YYYY-MM-DD hh:mm:ss");
if ($current ge $timeout_time) {
system("kill -9 $pid");
$pid_hash->{$itmp}->{pid} = 0;
}
else {
$tag = 1;
}
}
else {
$pid_hash->{$itmp}->{pid} = 0;
}
}
}
if ($tag == 0) {
last;
}
sleep 3;
}
exit 0;
问题:
1.子进程创建后,执行&get_file_content($table, $i);后,遇到exit(0);该进程就结束了么??
2.父进程该怎么结束(我执行这段代码后,如果不kill的话,改程序永远也执行不完,光标总在最后一行闪烁,执行用ctrl+c结束掉,但是文件已经都处理完了)?
3.下面的代码也存在这个问题,我也不知道怎么才能退出?
#!/usr/bin/perl
# test_proc_3.pl
# test multi process
# create by lianming: 2009-08-12
use strict;
use warnings;
use POSIX ":sys_wait_h";
## == number of proc ==
my $num_proc = 0;
## == number of collected ==
my $num_collect = 0;
my $collect;
## == get the child signal ==
$SIG{CHLD} = sub { $num_proc-- };
for (my $i = 0; $i < 10; $i ++) {
## == fork a new process ==
my $pid = fork();
if (!defined($pid)) {
print "Error in fork: $!";
exit 1;
}
if ($pid == 0) {
## == child proc ==
print "Child $i : My pid = $$\n";
sleep(5);
print "Child $i : end\n";
exit 0;
}
$num_proc ++;
## == if need to collect zombies ==
if (($i-$num_proc-$num_collect) > 0) {
while (($collect = waitpid(-1, WNOHANG)) > 0) {
$num_collect ++;
}
}
do {
sleep(1);
} until ($num_proc < 3);
}
exit 0;
$num_proc:正在活动的进程数量,控制在3个以内,所以在父进程每次fork完子进程后,都会检查这个变量,如果超出了3个,那就等一会。当父进程fork了新子进程的时候,这个数字会增加,当子进程退出以后,父进程捕获了信号,这个数字会减少。
$num_collect:已回收的进程数量,每回收一个子进程,变量加一。
$i:已经fork的进程数量。
$num_proc和$num_collect的和应该是等于$i的,如果不等于了,那就说明,有子进程需要回收了。
以上的红字儿是解释,但是为什么执行完后,光标还是不停地闪烁呢,用waitpid不是可以回收进程么??怎么才能让光标不闪烁执行完毕(专业词儿我不懂,大概就是这个意思吧)??
谢谢了,真的是刚入门,原来做.net的,对多进程一窍不通,已经看了2天了,也没啥眉目,希望大家帮助我一下吧,谢谢啦~~~~ |
|