2009-11-25 3 views
5

Я хотел бы запускать произвольные консольные подпроцессы и управлять ими из одного основного процесса. Консольные подпроцессы взаимодействуют через stdin, stdout и stderr, и если вы запускаете их в подлинной консоли, они прекращают работу при нажатии CTRL + C. Некоторые из них на самом деле могут быть деревом процессов, таких как пакетный скрипт, который запускает исполняемый файл, который, в свою очередь, может запускать другой исполняемый файл для выполнения некоторой работы. Я хотел бы перенаправить свои стандартные операции ввода-вывода (например, чтобы я мог показать их вывод в окне графического интерфейса) и в определенных обстоятельствах отправить им событие CTRL + C, чтобы они полностью отказались и закончили.Отправить CTRL + C в дерево подпроцессов в Windows

Следующие две диаграммы показывают первую нормальную структуру: один мастер-процесс имеет четыре подпроцесса рабочих, и некоторые из этих рабочих имеют свои собственные подпроцессы; и тогда, что должно произойти, когда один из рабочих должен быть остановлен - он и все его дети должны получить событие CTRL + C, , но никакие другие процессы не должны принимать событие CTRL + C.

Process diagram http://pics.livejournal.com/clockworksaint/pic/0007z5yr/s640x480.png

Кроме того, я бы предпочел, что нет никаких дополнительных окон, видимых пользователю.

Вот что я пытался (обратите внимание, что я работаю в Python, но решения для C-прежнему будет полезно):

  • нерест дополнительный промежуточный процесс с CREATE_NEW_CONSOLE, а затем с его нерест рабочий процесс. Затем позвоните по телефону GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0), когда мы хотим убить рабочего. К сожалению, CREATE_NEW_CONSOLE, по-видимому, мешает мне перенаправлять стандартные каналы ввода-вывода, поэтому мне остается без труда вернуть результат в основную программу.
  • Нерест дополнительного промежуточного процесса с CREATE_NEW_PROCESS_GROUP, а затем с его созданием рабочего процесса. Затем позвоните по телефону GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0), когда мы хотим убить рабочего. Так или иначе, это удается отправить CTRL + C только в мастер-процесс, что совершенно бесполезно. При ближайшем рассмотрении GenerateConsoleCtrlEvent говорит, что CTRL + C не может быть отправлен в группы процессов.
  • Нерест подпроцесса с CREATE_NEW_PROCESS_GROUP. Затем позвоните GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid), чтобы убить рабочего. Это не идеально, потому что CTRL + BREAK менее дружелюбен, чем CTRL + C, и, вероятно, приведет к беспорядочному завершению. (Например, если это процесс Python, никакой KeyboardInterrupt не может быть пойман и никакие окончательные блоки не выполняются.)

Есть ли хороший способ сделать то, что я хочу? Я могу видеть, что я мог бы теоретически основываться на первой попытке и найти другой способ общения между процессами, но я беспокоюсь, что это будет крайне неудобно. Есть ли хорошие примеры других программ, которые достигают такого же эффекта? Это кажется настолько простым, что это не может быть все, что необычно.

ответ

1

Я не знаю об управлении/перенаправлении stdin et. al., но для управления деревом подпроцессов вы рассмотрели использование Windows Job Objects api?

Есть еще несколько вопросов об управлении деревьями процесса (How do I automatically destroy child processes in Windows?Performing equivalent of “Kill Process Tree” in c++ on windows), и он выглядит как самый чистый метод, если вы можете его использовать.

В главе 5 из Windows Via C/C++ by Jeffery Richter обсуждается использование CreateJobObject и связанных с ним API.

+0

Я изучал объекты работы раньше, но единственным механизмом, который они обеспечивают для прекращения работы, является принудительное прекращение его процессов. Причина, по которой я хочу отправить CTRL + C, - дать процессам возможность закончить чисто. Обратите внимание, что группы процессов и CTRL_BREAK_EVENT выполняют удовлетворительную работу, если мне не нужна специальная отправка CTRL + C. – Weeble

Смежные вопросы