Определить, запущен ли уже процесс, и сотрудничать с ним - PullRequest
8 голосов
/ 09 января 2010

Я пытаюсь создать программу, которая запускает пул процессов, скажем, из 5 процессов, выполняет некоторую операцию, а затем завершает работу, но оставляет 5 процессов открытыми. Позже пользователь может снова запустить программу, и вместо запуска новых процессов он использует существующие 5. В основном это модель производитель-потребитель, где:

  1. Количество производителей варьируется.
  2. Количество потребителей постоянно.
  3. Производители могут быть запущены в разное время разными программами или даже разными пользователями.

Я использую встроенный модуль multiprocessing, в настоящее время в Python 2.6.4., Но с намерением в конечном итоге перейти на 3.1.1.

Вот базовый сценарий использования:

  1. Начальное состояние - процессы не запущены.
  2. Пользователь запускает program.py operation - один производитель, работает пять потребителей.
  3. Операция завершена - работает пять потребителей.
  4. Пользователь запускает program.py operation - один производитель, работает пять потребителей.
  5. Пользователь запускает program.py operation - два производителя, работают пять потребителей.
  6. Операция завершена - работает один производитель, работают пять потребителей.
  7. Операция завершена - работает пять потребителей.
  8. Пользователь запускает program.py stop и завершает его - процессы не запущены.
  9. Пользователь запускает program.py start и завершает работу - работает пять потребителей.
  10. Пользователь запускает program.py operation - один прокурор, работает пять потребителей.
  11. Операция завершена - работает пять потребителей.
  12. Пользователь запускает program.py stop и завершает - ни один процесс не запущен.

Проблема в том, что я не знаю, с чего начать:

  1. Обнаружение запущенных пользовательских процессов.
  2. Получение доступа к ним из ранее не связанной программы.
  3. Выполнение 1 и 2 кроссплатформенным способом.

Как только я смогу это сделать, я знаю, как управлять процессами. Должен быть надежный способ обнаружения существующих процессов, поскольку я видел, как Firefox делал это, чтобы предотвратить запуск нескольких экземпляров Firefox, но я не знаю, как это сделать в Python.

Ответы [ 3 ]

2 голосов
/ 09 января 2010

Существует несколько распространенных способов выполнить ваш пункт № 1 (обнаружение запущенных процессов), но для их использования сначала потребуется немного изменить свою мысленную картину того, как эти фоновые процессы запускаются при первом вызове программы. .

Думайте о первой программе не как о запуске пяти процессов и затем о выходе, а скорее как об обнаружении того, что это первый экземпляр, запущенный и не выходящий. Он может создать блокировку файла (один из распространенных подходов для предотвращения запуска нескольких приложений) или просто привязать к некоторому сокету (другой распространенный подход). Любой подход вызовет исключение во втором экземпляре, который затем знает, что он не первый, и может переориентировать свое внимание на контакт с первым экземпляром.

Если вы используете multiprocessing, вы можете просто использовать поддержку Manager , которая включает в себя привязку к сокету для работы в качестве сервера.

Первая программа запускает процессы, создает очереди, прокси или что-то еще. Он создает диспетчер, чтобы разрешить доступ к ним, возможно, разрешив удаленный доступ .

Последующие вызовы сначала пытаются связаться с указанным сервером / менеджером по предопределенному сокету (или использовать другие методы для обнаружения сокета, в котором он включен). Вместо того чтобы делать server_forever() вызов, они connect() и общаются, используя обычные механизмы multiprocessing.

1 голос
/ 09 января 2010

Вам нужна модель клиент-сервер в локальной системе. Вы можете сделать это с помощью сокетов TCP / IP для связи между вашими клиентами и серверами, но быстрее использовать локальные именованные каналы, если вам не нужно общаться по сети.

Основные требования к вам, если я правильно понял, таковы:
1. Производитель должен иметь возможность порождать потребителей, если их уже нет.
2. Производитель должен иметь возможность общаться с потребителями.
3. Производитель должен быть в состоянии найти уже существующих потребителей и общаться с ними.
4. Даже если производитель завершит работу, потребители должны продолжать работать.
5. Более одного производителя должны иметь возможность общаться с потребителями.

Давайте разберемся с каждым из них по очереди:

(1) - это простая проблема создания процесса, за исключением того, что потребительские (дочерние) процессы должны продолжать работать, даже если завершает работу производитель (родительский). См. (4) ниже.

(2) Производитель может общаться с потребителями, используя именованные каналы . См. os.mkfifo () и unix man-страницу из mkfifo () для создания именованных каналов.

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

(4) Для этого вам нужно будет использовать os.setuid () и заставить потребительские процессы действовать как демон. Смотрите unix справочную страницу от setsid ().

(5) Этот хитрый. Несколько производителей могут общаться с потребителями, используя один и тот же именованный канал, но вы не можете передать больше, чем «PIPE_BUF», объем данных от производителя к потребителю, если вы хотите надежно определить, какой производитель отправил данные, или если вы хотите предотвратить какое-либо чередование данных от разных производителей.

Лучший способ сделать (5) состоит в том, чтобы потребители открывали «управляющий» именованный канал (/tmp/control.3456, 3456 - pid потребителя) при выполнении. Производители сначала настраивают канал связи, используя «контрольный» канал. Когда производитель подключается, он отправляет свой pid, скажем, «1234», потребителю по каналу «control», который говорит потребителю создать именованный канал для обмена данными с производителем, например, «/tmp/data.1234». Затем производитель закрывает канал «control» и открывает «/tmp/data.1234» для связи с потребителем. У каждого потребителя могут быть свои собственные «контрольные» каналы (используйте пиды потребителей, чтобы различать каналы разных потребителей), и каждый производитель получает свою собственную «трубу данных». Когда производитель заканчивает , он должен очистить вверх по каналу данных или сказать потребителю сделать это. Точно так же, когда потребитель заканчивает, он должен очистить свои контрольные трубы.

Сложность заключается в том, чтобы не допустить одновременного подключения нескольких производителей к каналам управления одного потребителя. Канал «управления» здесь является общим ресурсом, и вам нужно синхронизировать между разными производителями, чтобы получить к нему доступ. Используйте для него семафоры или блокировку файла . См. posix_ipc модуль Python для этого.

Примечание: я описал большую часть вышеизложенного в терминах общей семантики UNIX, но все, что вам действительно нужно, - это способность создавать процессы-демоны, возможность создавать «именованные» каналы / очереди / все, что бы они могли быть найдены несвязанный процесс и возможность синхронизации между несвязанными процессами. Вы можете использовать любой модуль python, который обеспечивает такую ​​семантику.

1 голос
/ 09 января 2010

Взгляните на эти различные механизмы обнаружения служб: http://en.wikipedia.org/wiki/Service_discovery

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

Bonjour / zeroconf довольно хорошо поддерживается кроссплатформенным. Вы даже можете настроить Safari для показа вам сервисов zeroconf в вашей локальной сети, так что вы можете использовать это для отладки рекламы сервиса для потребителей. Одним из побочных преимуществ такого подхода является то, что вы можете легко запускать производителей на машинах, отличных от потребителей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...