完全创建和终止进程以及 child 个进程

Creating and killing processes and child processes completely

我有一个程序 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() 创建 child 个进程,每个 child 使用 system 启动一个记事本实例。 parent 进程试图用 taskkill 终止记事本进程,并循环重复。

该程序在停止前仅生成(并终止)了 64 个记事本实例。很明显,我没有正确处理这些过程,并且周围有一些位填充了某种 table.

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

奇怪的是 system 调用产生一个负值 $pid 但这些 PID 无法被 taskkill 或任务管理器识别。

如何在不达到限制的情况下生成和终止许多记事本实例?

编辑:按照暴民的想法,这是另一个脚本,但它仍然不会让我产生并杀死超过 64 个记事本: $出口=''; $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 的用途 - 你能澄清一下你的意思吗?我需要杀戮,而不是等待。 (同样,不是搜索引擎的短语!)。

EDIT2Parallel::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;
}

这基本上完成了第一次编辑所做的工作,但不知何故做得更干净 - 也许擦掉了早期工作所做的 child 的残余。我仍然很想知道为什么!

每一秒,它都会启动一个 child 进程,运行 $pm->start$pm->finish 之间的代码。 child 在杀死记事本并死亡之前存活了 10 秒,这允许大约 10 个记事本在任何时候存活。他们最重要的是,在整个程序退出之前,超过 64 个记事本可以生存和死亡。

我本来想从主进程中终止每个程序,但我知道我希望它在启动之前就结束,这应该可行。

还有很多要尝试的 - 感谢到目前为止的帮助,你可以称之为已解决(ish)。

对于这样的事情,在 Windows 上,您可能想尝试 underdocumented system 1, LIST syntax

system(1, @args) spawns an external process and immediately returns its process designator, without waiting for it to terminate. Return value may be used subsequently in "wait" or "waitpid".

重要的是,return 值是一个正确的进程 ID,可以传递给 taskkill(以及 Perl 的 waitpid),而不是 伪- 您从 Windows 上的 fork 调用中获得的进程 ID(负数)。无需使用此语法的 fork 调用。

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

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