首页 > 解决方案 > 完全创建和杀死进程和子进程

问题描述

我有一个程序,它在 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,并在循环中重复此过程。

该程序在停止之前仅生成(并杀死)64 个记事本实例。很明显,我没有正确处理这些过程,并且周围有一些东西会填满某种表格。

如果我不杀死记事本,仍然有 64 个限制。这可能表明我的清理工作不起作用,我已经杀死了记事本进程,但让孩子活着。

奇怪的是,该system调用产生了否定结果,但任务管理器或任务管理器$pid无法识别这些 PID 。taskkill

如何在不达到限制的情况下生成并杀死许多记事本实例?

编辑:按照暴民的想法,这是另一个脚本,但它仍然不会让我产生并杀死超过 64 个记事本:$exit=''; $计数=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感谢鲍罗丁!)

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)。

标签: perlprocessparent-child

解决方案


对于这样的事情,在 Windows 上,您可能想尝试未充分记录的system 1, LIST语法

system(1, @args)生成一个外部进程并立即返回其进程指示符,而不等待它终止。返回值可以随后在“wait”或“waitpid”中使用。

重要的是,返回值是可以传递给taskkill(以及 Perl 的waitpid)的正确进程 id,而不是您从Windows 上的调用中获得的伪进程 id(负数) 。fork不需要使用fork这种语法的调用。

$n = "001";
while (-f "datafile$n.txt") {
    $pid = system 1, "fancyprogram.exe", "datafile$n.txt";
    $n++;
    ...
}

像这样的模块Forks::Super在需要管理大量后台进程的脚本中也有很大帮助。它可以帮助的一些方法是限制后台作业的数量(一次只运行你的系统可以合理处理的尽可能多的作业),在后台作业上设置超时,或者在作业上设置优先级或 CPU 亲和性。


推荐阅读