- 论坛徽章:
- 2
|
本人小白,对pipe() 以及句柄的认识不清楚。查过一些资料仍然没有解决,特来求助。
需求:
fork多个子进程,模拟数据库查询操作,记录操作时间通过管道返回给主进程(我用的是pipe()函数)。
然后主进程进行处理。
代码如下
*****************************************************
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use Time::HiRes qw/time/;
use POSIX ":sys_wait_h";
my $count = $ARGV[0];
my $driver = "mysql";
my $database = "www";
my $dsn = "DBI driver:database=$database";
my $userid = "root";
my $password = "123456";
my $zombies = 0;
my @READER;
my @WRITER;
my @time;
my $time_avg;
$SIG{CHLD} = 'IGNORE';
sub RESOLVE {
my $pid;
while (($pid = waitpid(-1, WNOHANG)) > 0) {
print " id: $pid 子程序退出了。\n";
}
}
sub child {
my $i = $_[0];
print "I'm chid $i, my pid : $$\n";
close $READER[$i];
my $time_start = time();
my $dbh = DBI->connect($dsn, $userid, $password) or die $DBI::errstr;
my $sth = $dbh->prepare("SELECT * FROM test" ; #预处理语句
$sth->execute() or die $DBI::errstr;
my $time_accomplish = time();
#循环输出查询的数据
while ( my @row = $sth->fetchrow_array() ){
print join("\t", @row)."\n";
}
my $time_this = $time_accomplish-$time_start;
# print "本次查询用时:".$time_this."s\n";
###############################
select $WRITER[$i];
$| = 1;
print $time_this;
$sth->finish();
$dbh->disconnect();
sleep(3);
print "Child $i is done\n";
exit 0;
###############################
}
sub parent {
my $i = $_[0];
print "I'm parent : My pid = $$\n";
push @time, <$READER[$i]>;
close $WRITER[$i];
}
for (my $i = 1; $i <= $count; $i++) {
pipe ($READER[$i],$WRITER[$i]) or die " ipe failed: $!";
my $pid = fork();
if (not defined $pid){
print "Error in fork: $!\n";
exit 1;
}elsif ($pid == 0) {
child ($i);
}else {
parent ($i);
}
}
#RESOLVE;
foreach my $time_each (@time){
print "$time_each s\n";
};
print "主进程pid : $$ END\n";
exit 0
*************************************************************
执行过后输出如下:
./process.pl 2
I'm parent : My pid = 10473
I'm chid 1, my pid : 10474
I'm parent : My pid = 10473
I'm chid 2, my pid : 10475
GLOB(0xc8da1 s
GLOB(0xc8db80) s
主进程pid : 10473 END
1 huahua 18 alibaba 0.8
2 fanfan 20 nihong 2.8
3 hihi 25 yahoo 6.6
1 huahua 18 alibaba 0.8
2 fanfan 20 nihong 2.8
3 hihi 25 yahoo 6.6
************************************************************
主要的问题:
1. 输出中的这两个字符串代表什么?
GLOB(0xc8da1 s
GLOB(0xc8db80) s
2. 是否是因为pipe() 用法不对,其中的两个句柄可否用数组元素?
我在child子进程中直接使用 print $WRITER[$i] $time_this; 为什么会报错,提示 $time_this前需要操作符?
即编译器没有把 $WRITER[$i] 这个整体当作一个 handle?
3. 句柄的写法(类型)究竟有什么限制?
使用WRITER 是正常的,$WRITER[$i] 这种变量就不可以吗,为什么 pipe 仍然创建成功了?
4. 多个子进程和一个父进程单向通信,是否必须使用多个管道?
如果为在for 循环里 每个管道pipe() 创建时,都写成 pipe( READER,WRITER),那么perl 实际上做了什么?
是每次都创建一个新的pipe 吗?
还是每次都用已经存在的pipe 来返回,并没有创建新的?
或者是每次创建了新的,因为handle 名已经存在,所以用新的pipe 替换了 旧的,也就是说旧的pipe 被覆盖了,找不到了?
5. 如果必须用不同 handle 名来创建pipe 的话,正确的写法是什么?
以上。提前谢谢大家!~
|
|