[Python, Параллельное программирование, Разработка под Linux] Клиент-серверный IPC на Python multiprocessing
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Статья отражает личный опыт разработки 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.py
│ └── __init__.py
├── main.py
core — это пакет, в который можно положить модули с любой логикой. В модуле api реализованы методы обращения процессов друг к другу.Реализация API клиента
from multiprocessing.connection import Client
from multiprocessing.connection import Listener
# адрес сервера (процесса в руте) для исходящих
# запросов
daemon = ('localhost', 6000)
# адрес клиента (этого процесса) для входящих
# ответов от сервера
cli = ('localhost', 6001)
def send(request: dict) -> bool or dict:
"""
Принимает словарь аргументов удалённого метода.
Отправляет запрос, после чего открывет сокет
и ждет на нем ответ от сервера.
"""
with Client(daemon) as conn:
conn.send(request)
with Listener(cli) as listener:
with listener.accept() as conn:
try:
return conn.recv()
except EOFError:
return False
def hello(name: str) -> send:
"""
Формирует уникальный запрос и вызывает функцию
send для его отправки.
"""
return send({
"method": "hello",
"name": name
})
В модуле connection пакета multiprocessing есть два класса, реализующих API высокого уровня над низкоуровнивым аналогом стандартной библиотеки — socket.Client — класс, который содержит методы отправки дейтаграмм.Listener принимает дейтаграммы.Отправляемые запросы содержат название целевого метода сервера.Причем запросы не требуют никаких преобразований на сервере, ведь он тоже написан на Python, который интерпретирует поступающие данные также, как и клиент. Всё это происходит «под капотом» и не может не радовать.Использование APIВ main.py я импортирую модуль api для дальнейшего использования.
from core import api
response = api.hello("World!")
print(response)
Этот код представлен для демонстрации. В работе я использовал Сlick Framework для создания СLI приложения с опциями, которые вызывают методы API.Реализация API сервераПо идее метод должен выполнять системный вызов, который требует прав суперпользователя. Иначе всё это теряет смысл.
def hello(request: dict) -> str:
"""
Привилегированный системный вызов.
"""
return " ".join(["Hello", request["name"])
Использование API
from core import api
from multiprocessing.connection import Listener
from multiprocessing.connection import Client
# адрес сервера (этого процесса) для входящих запросов
daemon = ('localhost', 6000)
# адрес клиента для исходящих ответов
cli = ('localhost', 6001)
while True:
with Listener(daemon) as listener:
with listener.accept() as conn:
request = conn.recv()
if request["method"] == "hello":
response = api.hello(request)
with Client(cli) as conn:
conn.send(response)
Сервер должен быть активен всегда, поэтому я запускаю его в бесконечном цикле.Таким образом он всегда слушает порт 6000 и, при поступлении дейтаграммы, анализирует запрос. Затем он вызывает указанный в запросе метод и возвращает результат исполнения клиенту.ДополнительноСоветую снабдить свой сервер пакетом systemd, который позволяет программам на Python писать лог в journald.Для сборки вы можете использовать pyinstaller — он запакует ваш код в бинарный файл со всеми зависимостями. Не забудьте про соглашение о наименовании исполняемых файлов, упомянутое ранее.Спасибо за внимание!
===========
Источник:
habr.com
===========
Похожие новости:
- [Open source, *nix] FOSS News №51 – дайджест материалов о свободном и открытом ПО за 4-10 января 2021 года
- [Настройка Linux, PHP, Oracle] Как настроить мониторинг любых бизнес-процессов, в БД Oracle + построение графиков, используя бесплатную версию Grafana
- [Open source, *nix] Спецвыпуск FOSS News №50 – главное за 2020 год
- [Big Data, Машинное обучение, Карьера в IT-индустрии] Самообучение в Data science, с нуля до Senior за два года
- [Настройка Linux, Разработка на Raspberry Pi, Смартфоны, Умный дом] Делаем из старого усилителя многофункциональный медиа сервер с помощью Raspberry pi
- Релиз дистрибутива Linux Mint 20.1
- [GitHub, Разработка под Linux, Настольные компьютеры, Ноутбуки, IT-компании] Краудфандинговый проект Linux для Maс на M1 продолжает развиваться, он получил название Asahi Linux
- Релиз дистрибутива Slacko Puppy 7.0
- [Настройка Linux, Системное администрирование, Сетевые технологии] Установка NTP сервера для включения его в pool.ntp.org
- [Настройка Linux, Разработка под Windows] В тестовой сборке Windows 10 появилась возможность автоматически выполнять команды Linux при запуске дистрибутивов в WSL
Теги для поиска: #_python, #_parallelnoe_programmirovanie (Параллельное программирование), #_razrabotka_pod_linux (Разработка под Linux), #_python, #_ipc, #_multithreading, #_linux, #_python, #_parallelnoe_programmirovanie (
Параллельное программирование
), #_razrabotka_pod_linux (
Разработка под Linux
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:16
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Статья отражает личный опыт разработки CLI приложения для Linux.В ней рассмотрен способ выполнения привилегированных системных вызовов процессом суперпользователя по запросам управляющей программы через строго описанный API.Исходный код написан на Python для реального коммерческого приложения, но для публикации абстрагирован от конкретных задач.Введение «Межпроцессное взаимодействие (англ. inter-process communication, IPC) — обмен данными между потоками одного или разных процессов. Реализуется посредством механизмов, предоставляемых ядром ОС или процессом, использующим механизмы ОС и реализующим новые возможности IPC». — Википедия
.
├── core │ ├── api.py │ └── __init__.py ├── main.py from multiprocessing.connection import Client
from multiprocessing.connection import Listener # адрес сервера (процесса в руте) для исходящих # запросов daemon = ('localhost', 6000) # адрес клиента (этого процесса) для входящих # ответов от сервера cli = ('localhost', 6001) def send(request: dict) -> bool or dict: """ Принимает словарь аргументов удалённого метода. Отправляет запрос, после чего открывет сокет и ждет на нем ответ от сервера. """ with Client(daemon) as conn: conn.send(request) with Listener(cli) as listener: with listener.accept() as conn: try: return conn.recv() except EOFError: return False def hello(name: str) -> send: """ Формирует уникальный запрос и вызывает функцию send для его отправки. """ return send({ "method": "hello", "name": name }) from core import api
response = api.hello("World!") print(response) def hello(request: dict) -> str:
""" Привилегированный системный вызов. """ return " ".join(["Hello", request["name"]) from core import api
from multiprocessing.connection import Listener from multiprocessing.connection import Client # адрес сервера (этого процесса) для входящих запросов daemon = ('localhost', 6000) # адрес клиента для исходящих ответов cli = ('localhost', 6001) while True: with Listener(daemon) as listener: with listener.accept() as conn: request = conn.recv() if request["method"] == "hello": response = api.hello(request) with Client(cli) as conn: conn.send(response) =========== Источник: habr.com =========== Похожие новости:
Параллельное программирование ), #_razrabotka_pod_linux ( Разработка под Linux ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:16
Часовой пояс: UTC + 5