Создание и уничтожение процессов и дочерних процессов полностью - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть программа, которая находится в 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 для запуска экземпляра Блокнота.Родительский процесс пытается завершить процесс Notepad с помощью taskkill, и это повторяется в цикле.

Программа генерирует (и убивает) только 64 экземпляра Notepad перед остановкой.Ясно, что я не обрабатываю эти процессы должным образом, и вокруг них есть биты, которые заполняют какую-то таблицу.

Если я не убиваю Блокнот, все равно есть ограничение 64. Это, возможно, указывает на то, чтомоя очистка не работает, и я убил процесс «Блокнот», но оставил ребенка в живых.

Как ни странно, вызов system дает отрицательный $pid, но эти PID не распознаются taskkill или TaskМенеджер.

Как мне сгенерировать и уничтожить множество экземпляров Блокнота, не превышая ограничения?

РЕДАКТИРОВАТЬ : Следуя соображениям моба, вот еще один сценарий, но он все же выиграл 'не позволяйте мне порождать и убивать более 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 (спасибо, Бородин!)

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 блокнотов могут жить и умирать до завершения всей программы.

Я хотел убить каждую программу из основного процесса, но, как я буду знать, когда я захочу, она умрет раньшеЯ запускаю его, это должно сработать.

Много больше, чтобы попробовать - спасибо за помощь, и вы можете назвать это решенным (иш).

1 Ответ

0 голосов
/ 20 сентября 2018

Для чего-то подобного и в Windows вы можете попробовать недооцененный синтаксис system 1, LIST .

system(1, @args) порождает внешний процесс и немедленно возвращает его указатель процесса, не дожидаясь его завершения.Возвращаемое значение может впоследствии использоваться в «wait» или «waitpid».

Важно, что возвращаемое значение - это правильный идентификатор процесса, который может быть передан в taskkill (а также в * 1012 в Perl).*), а не идентификатор псевдопроцесса (отрицательное число), полученный при вызове fork в Windows.Нет необходимости использовать вызов fork с этим синтаксисом.

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

Модуль, подобный Forks::Super, также может очень помочь в сценарии с большим количеством фоновых процессов.управлять.Это может помочь уменьшить количество фоновых заданий (запуская столько заданий за раз, сколько может разумно обработать ваша система), установить тайм-ауты для фоновых заданий или установить приоритеты или привязку ЦП к заданиям.

...