完全创建和杀死进程和子进程

时间:2018-09-20 17:22:43

标签: perl process parent-child

我有一个程序在Windows中,使用这样的命令从命令提示符处输入

C:\Users\AndyI> ./myprogram.exe datafile.txt

我想使用Perl程序创建datafile.txt的许多实例(例如datafile.001.txtdatafile.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)。

1 个答案:

答案 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亲和力。