perl多进程和进程池
来源:互联网 发布:js数值转换成字符串 编辑:程序博客网 时间:2024/04/20 03:15
故事:
事情是这样的。突然接到一个任务,要求把HDFS上的数据copy一倍,用于压力测试。我仔细检查了HDFS的数据,发现每个数据目录下的文件数量在1000个左右。要求把每个文件copy一遍,重命名,放在相同的目录下。于是,我就写了个perl脚本,依次对每个文件夹下的每个文件复制一次。
悲剧就这样发生了。脚本跑了两天,才完成了大概1/3的任务(被人喷了)。这个时候,我才意识到串行的任务操作是不可取的,一个直接的想法是使用多进程来同时启动多个任务(别问我问什么没有想到多线程)。于是就有了今天的话题。
正文:
脚本如下。很简单,只有三个函数,一个设置进程池的大小,一个负责任务的进程调度,一个负责等待所有任务执行结束。具体使用方法:首先把任务代码封装成一个函数;然后把任务函数地址和函数参数传递给调度函数,调度函数就会依照设置,调度多进程完成任务;最后调用等待函数等待所有的进程完成任务。
这里涉及到几个perl内置函数:
1,fork 。官方文档:http://perldoc.perl.org/functions/fork.html。用于生成一个子进程。系统从当前进程复制一个进程(子进程)出来,父进程和子进程都从fork调用点开始执行。对于父进程,fork返回子进程的PID,对于子进程,fork返回0(从而可以区分当前进程是父进程还是子进程)。如果fork调用失败,fork就会返回undef。
2,waitpid 。官方文档:http://perldoc.perl.org/functions/waitpid.html。在父进程中使用。通过这个函数探知子进程是否退出。使用子进程的PID调用该函数,waitpid(PID, wait_flag)。第一个参数如果是子进程的PID,表示等待该子进程退出;第一个参数如果是-1,表示等待所有的子进程退出(有任何一个子进程退出,就会返回)。第二参数表示如何等待子进程退出,可以阻塞等待,也可以非阻塞等待(这里使用了非阻塞等待,WNOHANG,with no hang?)。如果有子进程退出,就会返回该子进程的PID,如果没有(非阻塞时发生这种情况)就返回0,如果根本就没有子进程,就会返回-1。
3,wait 。官方文档:http://perldoc.perl.org/functions/wait.html。没有参数,调用等待子进程退出,返回退出子进程的PID。如果根本没有子进程,就返回-1,如果有很多子进程,其中任何一个(只需要一个)子进程退出,就会触发父进程的wait()返回。所以有几个子进程退出,wait就会正确返回几次。
NOTE:perl语言本身支持多进程(但是语言本身不支持多线程,多线程需要自己实现,可以参考threads模块的用法)
ProcessPool.pm
#!/usr/bin/perlpackage ProcessPool;require Exporter;use strict;use warnings;use POSIX ":sys_wait_h";use vars qw(@ISA @EXPORT $VERSION);@ISA = qw(Exporter);@EXPORT = qw(processpool_set_cnt processpool_waitforall processpool_run_task);$VERSION = 0.1;my $process_cnt = 10;my $current_cnt = 0;sub processpool_set_cnt{ if( @_ > 0 ){ $process_cnt = int($_[0]); $process_cnt = $process_cnt == 0 ? 10 : $process_cnt; print "set ok : process count: $process_cnt\n"; }}sub processpool_waitforall{ while($current_cnt > 0){ my $code = waitpid(-1, WNOHANG); if( $code > 0){ $current_cnt --; }elsif( $code == -1 ){ $current_cnt = 0; }else{ sleep(3); } } print "JOBs all DONE\n";}sub processpool_run_task{ my $func = shift@_; my @params = @_; while($current_cnt >= $process_cnt){ my $code = waitpid(-1, WNOHANG); if( $code > 0 ){ $current_cnt --; }elsif( $code == -1 ){ print "process count ERROR\n"; $current_cnt = 0; }elsif( $code == 0 ){ sleep(3); } } #do job my $pid = fork; if( ! defined($pid) ){ print "Process create FAILED: $func @params\n"; return 1; } if( $pid == 0 ){ #child process my $res = &{$func}(@params); exit $res; } $current_cnt++; return 0;}### tail1;
使用一个简单的测试程序,可以验证程序的正确性。
test.pl
#!/usr/bin/perl -w use lib '/home/user/myutil/base';use ProcessPool;processpool_set_cnt(3);for($i = 0; $i < 11; $i++){ processpool_run_task(\&work, $i);}processpool_waitforall();sub work{ print "work $_[0] running...\n"; sleep(30); print "work $_[0] done\n"; return 0;}
- perl多进程和进程池
- perl多进程编程
- Perl多进程实战
- Perl多进程实战
- perl 多进程基础
- Perl多进程
- Perl多进程实例
- perl fork多进程
- perl 多进程
- 限制perl多进程数量
- Perl多进程实战之一
- perl多进程读写文本
- Perl多进程实战之一
- perl多进程实战之一
- Perl多进程与信号量
- perl中创建多进程
- perl多进程主进程等子进程结束
- linux下perl和c进程通信
- poj 2425 A Chess Game_sg函数
- cygwin中sshd服务不能启动的解决方法
- Qt生成有图标的.exe文件
- STL中hashtable,hashset,hashmap,set,map,multiset和multimap的区别
- muParser公式库使用简介
- perl多进程和进程池
- strcpy函数
- Code Forces 357 B. Flag Day 暴力map
- 网站制作---网站伪静态的介绍
- 对比iOS中的四种数据存储
- 或许咱们可以打造一个信息共享平台
- swingfileChoseDemoTwo
- 最近做的一道随机问题,好像是int a[]={1,2,3,4,5,6,7,8,9}; 输出一个随机数组a[]={5,8,7,9,1,4,6,2,3};
- [SCOI2009]生日礼物