- Русские Блоги
- Межпроцессное взаимодействие в Python
- 1.1 Очередь имеет два метода:
- 1.2 Механизм связи труб,
- * Труба часто используется для двух процессов, два процесса расположены на обоих концах трубы
- * Метод Pipe возвращает (conn1, conn2), представляющий оба конца канала. Метод Pipe имеет дуплексный параметр. Значение по умолчанию — True, то есть полнодуплексный режим. Если это FALSE, conn1 отвечает только за получение информации, а conn2 отвечает за отправку.
- * Методы send и recv отправляют и получают информацию соответственно.
- Клиент-серверный IPC на Python multiprocessing
- Введение
- Предпосылки параллелизма
- Историческая справка
- Структура проекта
- Реализация API клиента
- Использование API
- Реализация API сервера
- Использование API
- Дополнительно
- Русские Блоги
- Межпроцессное взаимодействие Python
Русские Блоги
Межпроцессное взаимодействие в Python
Существует много способов взаимодействия между процессами, включая сигналы, каналы, очереди сообщений, семафоры, разделяемую память, сокеты и т. Д.
Существует два основных метода: Очередь и Труба. Очередь используется для связи между несколькими процессами. Труба — это связь между двумя процессами.
1.1 Очередь имеет два метода:
Метод put: для вставки данных в очередь он также имеет два необязательных параметра: заблокирован и время ожидания. Подробная информация о Baidu
Метод Get: чтение и удаление элемента из очереди. Точно так же у него есть два необязательных параметра: заблокирован и время ожидания. Подробная информация о Baidu
- Запустить скриншот:
1.2 Механизм связи труб,
* Труба часто используется для двух процессов, два процесса расположены на обоих концах трубы
* Метод Pipe возвращает (conn1, conn2), представляющий оба конца канала. Метод Pipe имеет дуплексный параметр. Значение по умолчанию — True, то есть полнодуплексный режим. Если это FALSE, conn1 отвечает только за получение информации, а conn2 отвечает за отправку.
* Методы send и recv отправляют и получают информацию соответственно.
Операционные результаты;
Python может реализовать разделяемую память между процессами через модуль mmap
Файловый объект mmap является как строкой, так и обычным файловым объектом. Когда это похоже на строку, мы можем изменить в ней один символ, такой как obj [index] = ‘a’, и мы также можем изменить короткий символ, такой как obj [2: 5] = ‘aaa’. Подобно объекту файла, потому что в mmap будет метка операции, мы можем использовать метод seek (), чтобы изменить метку операции объекта mmap.
Объект mmap создается с использованием метода mmap (). Системы Windows и Unix имеют разные методы построения.
Способ изготовления окон:
Метод построения Linux:
fileno — это метка файла, которая может быть меткой обычного файлового объекта (объект file получается методом fileno ()), или -1, что означает, что память безымянна. Параметр length определяет длину памяти, если она равна 0, берется максимальная длина файла, соответствующего fileno.accessЭто изменение прав доступа для объекта mmap, которые могут иметь три значения: ACCESS_READ, ACCESS_WRITE, ACCESS_COPY,
Значения флагов могут быть MAP_PRIVATE и MAP_SHARED. Значение по умолчанию — MAP_SHARED. Изменение параметра используется для определения того, является ли память частной или общей.
Значение prot может быть PROT_READ и PROT_WRITE, которые также используются для определения разрешений mmap.
flags + prot и access могут использоваться только в одном из режимов определения разрешений, иначе будет сообщено об ошибке
tagnameЯвляется ли метка этого mmap уникальной меткой для этой части разделяемой памяти, действующей как fileno
Из-за параметра tagname в windows вы можете задать fileno равным -1, а затем определить тэг, например «mysharename», чтобы несколько процессов могли совместно использовать одну и ту же память.
Однако в Linux этот метод нельзя использовать, только открыв файл и получив fileno.
Таким образом, в Windows общая память более гибкая
Общие методы для объектов mmap:
mmap.close () закрывает объект
mmap.find (string [, start [, end]]) находит содержимое в общей памяти и возвращает маркер операции с наименьшим соответствующим содержимым
mmap.flush ([смещение, размер]) сохраняет данные в памяти на жесткий диск
mmap.move (dest, src, count) метка операции перемещения
mmap.read (num) читает символы num длины из метки операции
mmap.read_byte () читает двоичные данные
mmap.readline () читает строку данных
mmap.resize (newsize) Изменить длину mmap
mmap.rfind (string [, start [, end]]) находит содержимое в общей памяти и возвращает тег операции с наибольшим соответствующим содержимым
mmap.seek (pos [, whwhence]) Переместить метку операции
mmap.size () возвращает длину объекта mmap
mmap.tell () возвращает позицию маркера текущей операции
mmap.write (строка) записывает содержимое.
mmap.write_byte (byte) записывает двоичный контент
Пример построения Linux:
Поскольку длина объекта mmap не может быть больше длины файла, в противном случае будет сообщено об ошибке: ValueError: смещение mmap больше размера файла
Поэтому в форме wb сначала откройте общий файл, а затем запишите длину общей памяти. После закрытия файла откройте файл в режиме r + b, а затем создайте объект mmap.
Конечно, в следующий раз вы можете напрямую открыть файл с помощью r + b, а затем создать объект.
Сигнал — способ, которым процессы общаются. Как только процесс получает сигнал, он прерывает исходный поток выполнения программы для обработки сигнала.
Несколько общих сигналов:
SIGINT Завершить процесс Прервать процесс (control + c)
SIGTERM Процесс завершения Сигнал завершения программного обеспечения
SIGKILL Завершает процесс Убивает процесс
Сигнал тревоги SIGALRM
По сравнению с разделяемой памятью сигналы более системно-ориентированы. Системы Linux также управляют процессами посредством сигналов, а система также определяет поведение определенных процессов после получения определенных сигналов.
Конечно, мы можем связать функции обработки сигналов, чтобы изменить поведение процесса после получения сигнала
Источник
Клиент-серверный IPC на Python multiprocessing
Статья отражает личный опыт разработки CLI приложения для Linux.
В ней рассмотрен способ выполнения привилегированных системных вызовов процессом суперпользователя по запросам управляющей программы через строго описанный API.
Исходный код написан на Python для реального коммерческого приложения, но для публикации абстрагирован от конкретных задач.
Введение
«Межпроцессное взаимодействие (англ. inter-process communication, IPC) — обмен данными между потоками одного или разных процессов. Реализуется посредством механизмов, предоставляемых ядром ОС или процессом, использующим механизмы ОС и реализующим новые возможности IPC». — Википедия
У процессов могут быть разные причины для обмена информацией. На мой взгляд, все они являются следствием политики безопасности ядра Unix.
Как известно, ядро Unix — это автономная система, которая функционирует без вмешательства человека. Собственно говоря, пользователь — это объект операционной системы, который появился чтобы обезопасить ядро от несанкционированного вмешательства.
Обеспечение безопасности ядра заключается в разделении адресного пространства операционной системы на пространство ядра и пространство пользователя. Отсюда два режима работы системы: режим пользователя и режим ядра. Причем, смена режимов — это переключение между двумя пространствами.
В режиме пользователя недоступны области памяти, зарезервированные ядром, как и системные вызовы, которые изменяют состояние системы.
Тем не менее таким доступом обладает суперпользователь.
Предпосылки параллелизма
Если ваша программа не использует привилегированные системные вызовы, вам не нужен суперпользователь, а значит можно писать монолит без параллелизма.
В противном случае вам придётся запускать свою программу под рутом.
На этом можно было бы закончить, если бы не проблема доступа к эксклюзивным ресурсам пользовательского окружения из окружения суперпользователя.
Представьте, что вы обращаетесь к ресурсу или к переменной окружения, которая присутствует только в пользовательском пространстве.
Например, служба, которая вам нужна, зависит от окружения рабочего стола, которое доступно только когда пользовательская сессия активна. В этом случае объект, который вам нужен просто не существует в окружении суперпользователя. Для того, чтобы получить к нему доступ, вам нужен процесс в пользовательском окружении, а для системных вызовов — процесс в руте.
При этом вы можете запросить у процесса в руте исполнение системного вызова из пользовательского процесса при помощи одного из методов IPC.
Таблица методов межпроцессного взаимодействия
Реализуется ОС или процессом
Все ОС, совместимые со стандартом POSIX.
Все ОС, совместимые со стандартом POSIX.
Очередь сообщений (Message queue)
Большинство ОС; в некоторых ОС, например, в Windows, сигналы доступны только в библиотеках, реализующих стандартную библиотеку языка Си, и не могут использоваться для IPC.
Все ОС, совместимые со стандартом POSIX.
Проецируемый в память файл (mmap)
Все ОС, совместимые со стандартом POSIX. При использовании временного файла возможно возникновение гонки. ОС Windows также предоставляет этот механизм, но посредством API, отличающегося от API, описанного в стандарте POSIX.
Обмен сообщениями (без разделения)
Используется в парадигме MPI, Java RMI, CORBA и других.
Все ОС, совместимые со стандартом POSIX.
Все ОС, совместимые со стандартом POSIX.
Для своего приложения я выбрал сокеты и написал API для коммуникации между процессами.
Таким образом в распоряжении конечного пользователя оказывается программа, которая не требует прав суперпользователя, но запрашивает исполнение системных вызовов у процесса в руте через соответствующий сокет.
При этом процесс в руте запускается при загрузке системы и остаётся активным всегда, прослушивая сокет на наличие входящих дейтаграмм.
Историческая справка
Традиционно процессы, которые запускаются при загрузке системы и остаются активными в фоне, классифицируются как daemon. Имена исполняемых файлов таких программ по соглашению заканчиваются на «d». Пример: systemd.
Программы пользовательского пространства, взаимодействующие с daemon можно назвать управляющими, что также по соглашению отражено в их названиях. Пример: systemctl.
Известны и другие примеры: ssh и sshd.
В более современной интерпретации их называют клиентами и серверами с тем отличием, что последние взаимодействуют по сетевым протоколам. Однако, это не мешает нам использовать сокеты исключительно для локальных процессов когда сокет принимает дейтаграммы через конвейер.
Структура проекта
Для сервера и клиента я использую одинаковую структуру.
core — это пакет, в который можно положить модули с любой логикой. В модуле api реализованы методы обращения процессов друг к другу.
Реализация API клиента
В модуле connection пакета multiprocessing есть два класса, реализующих API высокого уровня над низкоуровнивым аналогом стандартной библиотеки — socket.
Client — класс, который содержит методы отправки дейтаграмм.
Listener принимает дейтаграммы.
Отправляемые запросы содержат название целевого метода сервера.
Причем запросы не требуют никаких преобразований на сервере, ведь он тоже написан на Python, который интерпретирует поступающие данные также, как и клиент. Всё это происходит «под капотом» и не может не радовать.
Использование API
В main.py я импортирую модуль api для дальнейшего использования.
Этот код представлен для демонстрации. В работе я использовал Сlick Framework для создания СLI приложения с опциями, которые вызывают методы API.
Реализация API сервера
По идее метод должен выполнять системный вызов, который требует прав суперпользователя. Иначе всё это теряет смысл.
Использование API
Сервер должен быть активен всегда, поэтому я запускаю его в бесконечном цикле.
Таким образом он всегда слушает порт 6000 и, при поступлении дейтаграммы, анализирует запрос. Затем он вызывает указанный в запросе метод и возвращает результат исполнения клиенту.
Дополнительно
Советую снабдить свой сервер пакетом systemd, который позволяет программам на Python писать лог в journald.
Для сборки вы можете использовать pyinstaller — он запакует ваш код в бинарный файл со всеми зависимостями. Не забудьте про соглашение о наименовании исполняемых файлов, упомянутое ранее.
Источник
Русские Блоги
Межпроцессное взаимодействие Python
Межпроцессное взаимодействие Python в основном используется для обмена и передачи данных между процессами при наличии нескольких процессов.
Существует пять основных способов взаимодействия между процессами:
1. Конвейер
2. Очередь сообщений
3. Общая память
4. Сигнал
5. Сокет
тип файла linux
Общие типы файлов: —
Один из наиболее распространенных типов файлов в Linux, включая текстовые файлы (ASCII); двоичные файлы (двоичные); файлы формата данных (данные); различные сжатые файлы. Первый атрибут за[-]
Файл каталога: d
— это каталог, к которому можно получить доступ с помощью команды # cd. Первый атрибут — [d], например [drwxrwxrwx]
Блокировать файл устройства: b
Файл блочного устройства: это интерфейсное устройство, которое хранит данные для доступа к системе, короче говоря, это жесткий диск. Например, код первого жесткого диска — / dev / hda1 и другие файлы. Первый атрибут — [b]
Устройство символов: c
Файл символьного устройства: устройство интерфейса последовательного порта, такое как клавиатура, мышь и т. д. Первый атрибут — [c]
Файл сокета 😒
Этот тип файла обычно используется для сетевых подключений для передачи данных. Вы можете запустить программу для прослушивания запроса клиента, и клиент может передавать данные через сокет. Первый атрибут — [s], этот тип файла чаще всего встречается в каталоге / var / run.
Файл конвейера: p
FIFO также является особым типом файла, его основная цель — устранить ошибку, вызванную одновременным доступом к файлу нескольких программ. FIFO — это сокращение от first-in-first-out. Первый атрибут — [p]
1. Трубопровод
Функция конвейера в многопроцессорной обработке
p,q=Pipe(duplex)
Функция: создание конвейера
Параметры:
по умолчанию для дуплексного режима установлено значение True, что указывает на двунаправленность конвейера.
Если установлено значение False, конвейер является односторонним.
возвращаемое значение :
возвращает два объекта конвейерного потока, представляющие два конца конвейера соответственно.
Если параметр имеет значение True (по умолчанию) Оба объекта могут быть отправлены и приняты
Если false, первый объект может быть принят только, а второй объект может быть только отправлен.
2. Очередь сообщений
multiprocessing — 》 Queue
открывает в памяти модель очереди для хранения сообщений. Любой процесс, которому принадлежит объект очереди, может хранить и извлекать сообщения.
q=Queue(maxsize = 0)
Функция: создание объекта очереди сообщений
Параметры: maxsize по умолчанию равен 0, что означает, что сообщения, которые могут храниться в очереди сообщений, определяются пространством, автоматически выделяемым системой.
> 0 положительное целое число Указывает максимальное количество сообщений, хранящихся в очереди.
Возвращаемое значение: объект очереди сообщений
q.put()
Сохранять сообщение в очереди сообщений. Когда очередь сообщений заполнена, оно блокируется.
Тип сохраненного сообщения может быть списком чисел, строк и т. д.
q.full()
Оцените, заполнена ли очередь, если она заполнена, верните True, в противном случае верните False
q.qsize()
Просмотр количества сообщений в текущей очереди
q.get()
Получать сообщения по одному, когда очередь сообщений пуста, блокировать
q.empty()
Если очередь сообщений пуста, она вернет True. Если она не пуста, верните False.
параметр блока и параметр тайм-аута в get get
по умолчанию имеет значение True, что означает, что обе функции являются блокирующими.
Если установлено значение False, это означает отсутствие блокировки
тайм-аут. Если для блока задано значение True, это означает время ожидания тайм-аута.
3. Общая память
открывает область памяти для хранения данных в памяти, и содержимое, сохраняемое каждый раз, будет перезаписывать предыдущее содержимое. Поскольку нет модификации для форматирования памяти, скорость доступа высока.
from multiprocessing import Value,Array
obj = Value(ctype,obj)
Функция: открытие общей памяти
Параметр: ctype Тип c, который нужно преобразовать
obj начальное значение, которое будет записано в общую память.
Атрибут obj.value предназначен для получения значения из общей памяти.
obj = Array(ctype,obj)
Функция: открытие общего пространства памяти
параметр: тип c для преобразования
obj: данные, помещаемые в общую память, представляют собой список, и данные в списке должны быть того же типа.
Если obj передает положительное число, это означает, сколько места открыто в общей памяти. Тип значений, которые могут быть сохранены в пространстве, определяется ctype.
Возвращаемое значение: вернуть повторяемый объект, чтобы получить значение через цикл for, который можно изменить.
4. Сигнал
kill -l Просмотр системных сигналов
kill -signame PID отправляет сигнал signame процессу с PID номера процесса.
Сигнал: Название сигнала Значение Метод обработки по умолчанию
Имя: Определение системы
Значение: определение системы
Метод обработки: используйте метод по умолчанию для обработки (система определяет игнорирование прерывания паузы
Игнорировать сигнал (если сигнал не появился)
обрабатывается индивидуально
Как послать сигнал:
os.kill(pid,sig)
Функция: отправка сигнала процессу
Параметры: pid: номер PID процесса, который нужно отправить.
sig: сигнал для отправки
signal.alarm(sec)
Функция: отправить себе тактовый сигнал (SIGALRM)
Параметры: sec: количество секунд означает, что тактовый сигнал будет отправлен через соответствующее количество секунд.
- Сигнал — это асинхронный метод межпроцессного взаимодействия.
- Если функция будильника используется несколько раз в процессе, последующее время будет перезаписывать предыдущее время.
signal.pause()
Блок, ожидающий появления сигнала
signal.signal(signum,handler)
Функция: обработка сигнала
Параметры: signum: указывает сигнал, который может быть обработан
handler: метод обработки сигнала
Метод обработки по умолчанию: SIG_DFL
Игнорировать сигнал: SIG_IGN
Индивидуальный метод: функция
Функция сигнала также является функцией асинхронной обработки сигнала.
SIGSTOP и SIGKILL не могут быть обработаны сигнальной функцией
Схема обработки сигналов зомби-процесса В родительском процессе
5. Розетка
Используйте локальные сокеты для межпроцессного взаимодействия
Источник