我有一个程序在Windows中,使用这样的命令从命令提示符处输入
C:\Users\AndyI> ./myprogram.exe datafile.txt
我想使用Perl程序创建datafile.txt
的许多实例(例如datafile.001.txt
,datafile.002.txt
等)并调用myprogram.exe
来并行处理它们。
这个通用程序说明了一些问题
$exit = '';
$count = 0;
while ( $exit eq '' ) {
$pid = fork();
if ( $pid == 0 ) { # if this is a child process
$exit = 'yes';
system 'notepad.exe'; # open an instance of Notepad
}
else {
system("taskkill /im notepad.exe /f"); # Kill all instances
$count++;
print "$count instances\n";
}
if ( $count > 500 ) { # In case of infinite loop
$exit = 'yes';
}
}
sleep 100; # So I have time to read the output
我正在使用fork()
创建子进程,每个子进程都使用system
启动记事本实例。父进程尝试使用taskkill
杀死Notepad进程,并在循环中重复进行。
程序在暂停之前仅生成(杀死)64个记事本实例。显然,我没有正确地处理这些过程,周围有一些位会填满某种表。
如果我不杀死记事本,则仍然有64个限制。这也许表明我的清理工作不起作用,并且杀死了记事本进程,但让孩子活了。
奇怪的是,system
调用会产生负数$pid
,但是taskkill
或任务管理器无法识别这些PID。
如何在不超出限制的情况下生成并杀死许多记事本实例?
编辑:按照暴民的想法,这是另一个脚本,但是它仍然不能让我产生并杀死64个以上的记事本: $ exit =''; $ count = 0;
while($exit eq ''){
$pid=system 1,'notepad.exe'; # open an instance of Notepad
print "$pid\n";
sleep 1; # Slows it down for easy viewing - not necessary
system("taskkill /pid $pid /f"); # Kill by PID
$count++;
print"$count instances\n";
if($count>100){ # in case of infinite loop!
$exit='yes';
}
}
sleep 100; # so I have time to read the output!
有什么想法吗?我还没有找到用于waitpid或wait的方法-您能说明您的意思吗?我需要杀死,而不是等待。 (同样,不是搜索引擎的短语!)。
EDIT2 :Parallel::ForkManager
(感谢Borodin!)
use Parallel::ForkManager;
my $pm=Parallel::ForkManager->new(20); # maximum number of child processes at any one time
PROGS:
for(my $i=1;$i<=100;$i++){
print"$i\n";
sleep 1;
$pm->start and next PROGS;
my $pid=system 1,'notepad.exe';
sleep 10;
system("taskkill /pid $pid /f");
$pm->finish;
}
从本质上讲,它可以完成第一次编辑的操作,但是可以更干净地完成它-可以像早期的工作一样清除孩子的残余物。我还是很想知道为什么!
每秒钟,它都会启动一个子进程,该子进程在$pm->start
和$pm->finish
之间运行代码。这个孩子在杀死记事本并垂死之前可以生存10秒钟,这使得任何时候都可以生存大约10个记事本。而且至关重要的是,在整个程序退出之前,有超过64个记事本可以生存和死亡。
我本来想从主进程中删除每个程序,但是正如我将要知道的那样,在我启动它之前它会死掉,这应该可以工作。
还有很多可以尝试的-到目前为止,我们非常感谢您的帮助,您可以将其称为已解决(ish)。
答案 0 :(得分:1)
对于类似这样的事情,在Windows上,您可能需要尝试underdocumented system 1, LIST
syntax。
system(1, @args)
产生一个外部进程,并立即返回其进程指示符,而无需等待其终止。返回值 随后可以在“等待”或“ waitpid”中使用。
重要的是,返回值是可以传递给taskkill
(以及Perl的waitpid
)的正确进程ID,而不是伪进程ID ( Windows上通过fork
调用获得的负数)。无需使用带有这种语法的fork
调用。
$n = "001";
while (-f "datafile$n.txt") {
$pid = system 1, "fancyprogram.exe", "datafile$n.txt";
$n++;
...
}
像Forks::Super
这样的模块也可以在脚本中提供很多帮助,这些脚本需要管理许多后台进程。它可以帮助解决的一些方法包括限制后台作业的数量(一次仅运行系统可以合理处理的尽可能多的作业),为后台作业设置超时或为作业设置优先级或CPU亲和力。