LINUX.ORG.RU

Покритикуйте идею IPC

 


0

3

Приветствую.

До сих пор периодически возникает бугуртящий вопрос «ну почему D-BUS»?

Попробовал реализовать IPC через shared memory.

Итак, есть один относительно большой файл (мегабайт, или даже два, в зависимости от количества программ, его использующих).

Файл доступен через вызовы ФС, и расположен в условно говоря /dev/shm/file.

Файл в формате JSON.

Когда программе нужно передать какие-то данные другим программам - она сначала читает этот файл в строку, конвертирует в свой блок переменных, добавляет новую переменную в этот блок, конвертирует обратно в JSON и записывает в файл.

Думаю о механизме блокировок говорить не нужно, программа не начнет обрабатывать чтение\запись до тех пор пока висит блокировка (или по тайм-ауту), а когда начнет обрабатывать - добавит уже свою блокировку, чтоб другие программы не писали.

Когда программе нужно прочитать данные - она просто читает этот файл, и достает оттуда интересующую ее переменную.

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

Для разграничения владельца, само собой формат переменных может представлять собой ассоциативный массив, где первый ключ - уникальное имя приложения. Шина, если по-dbus-ному.

Pro системы:

Абсолютная универсальность

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

JSON-формат прост, знаком всем, с *char работает любой ЯП, привести со своего нативного *char к своему же нужному типу - однозначно проще, чем с этих сраных variant, ss, a(sss) и прочего зоопарка велосипедов. Не говоря уже о том, что функции для парсинга JSON есть в любом современном и не очень ЯП.

Отсутствие посредника

Он попросту не нужен, посредник - сама ФС, которая уже и так есть. Кому нужно - пишет, кому нужно - читают, кому нужно - мониторят.

Соответственно небольшие накладные расходы, а значит производительность. Как ни крути, а записать в память\прочитать с памяти - намного быстрее, нежели дергать демон.

Гибкость

Вся модернизация, если такова необходима, делается силами самой программы, и того кому эта программа нужна.

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

Понятная простота

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

- - -

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

Все пока работает.

Посмотрите пожалуйста со стороны, и покритикуйте способ.

Благодарю.

★★★★★
Ответ на: комментарий от pfg

переделайте его так чтобы он решал ошибки моего кривого джойстика :)

Кривых девайсов всегда будет много. Они не должны мешать все остальной системе, и это не только моя проблема.

Но в багтрекер уже отписывался, спасибо за совет.

hateyoufeel ★★★★★
()
Ответ на: комментарий от windows10

Делаешь:

mkfifo /path/do/pipe

Натравливаешь на него всех своих «читателей» и одного «писателя», который может еще и данные периодически в свой файл сдампливать, а при холодном старте считывать. Если «писателей» больше одного - блокируй запись семафором. Можешь гонять в этом fifo голые JSON строки.

deep-purple ★★★★★
()
Ответ на: комментарий от madcore

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

Тогда, как уже сказали выше - юникс сокет, но тут нужен простейший сервер, который откроет сокет и будет акцептить всех читателей и писателей. Это лучше (чище), чем создавать N пайпов и писать в них. Плюс, защиту от конкурентной записи можно в самом сервере реализовать. Таким образом читатели даже думать не будут про какие-то блокировки.

deep-purple ★★★★★
()

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

Не останавливайся. Пусть программы пишут и читают сразу блоки дискового устройства. Никаких файлов, каталогов, прав, буферов и прочего мусора. Максимально приближенная к нативному программированию система: просто используем блоки данных другой программы, как свои собственные, и позволяем другой программе использовать наши блоки данных.

monk ★★★★★
()
Ответ на: комментарий от Vidrele

Вроде бы, IPC отдельно, shared memory отдельно. Решил использовать одно вместо другого - отлично. Может быть, для твоей задачи так и нужно. Но зачем называть одно другим?

Потому что IPC - это взаимодействие между программами. Shared memory - это участок, который может использоваться для такого взаимодействия.

Использовать васянсофт прикрученный сбоку чтобы программе№1 послать сигнал программе№2 - еще более дебильная идея, чем использовать для этого уже существующий участок памяти.

windows10 ★★★★★
() автор топика
Ответ на: комментарий от windows10

Не надо никакой васянсофт, ещё раз, отправлять сообщения уже умеет ядро, у него для этого есть сокеты. И они работают в большинстве случаев оптимальнее чем твоя самодельная реализация того же самого через общую память. И заодно они могут настраиваться и проверяться стандартными средствами ОС (sysctl, netstat), а для твоего эмулятора придётся это тоже реализовывать заново.

firkax ★★★★★
()
Ответ на: комментарий от firkax

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

deep-purple ★★★★★
()
Ответ на: комментарий от monk

dbus и так маленькое решение (250КБ). К тому же часть ОС.

Размер решения состоит не в том, сколько оно занимает места, а в том насколько оно усложняет код.

dbus - усложняет, потому что в отличие от того же сокета оперирует не строкой (пардон, набором байтов), а своими неповторимыми костылями. Пожалуй это хрестоматийный пример того, как не надо писать софт.

windows10 ★★★★★
() автор топика
Ответ на: комментарий от firkax

Не надо никакой васянсофт, ещё раз, отправлять сообщения уже умеет ядро, у него для этого есть сокеты. И они работают в большинстве случаев оптимальнее чем твоя самодельная реализация того же самого через общую память. И заодно они могут настраиваться и проверяться стандартными средствами ОС (sysctl, netstat), а для твоего эмулятора придётся это тоже реализовывать заново.

Ну, частично ты прав. Только оркестровать это все равно придется.

В случае обмена средствами ФС (я пишу скорее об ФС, а общая память - это просто для быстрой скорости), этим занимается сама ФС: программа А может послать программе Б «сигнал», а программа В может этот сигнал поймать независимо от функционирования программы Б.

В случае с сокетами, программа Б должна уметь обрабатывать сам сигнал от программы А, и запрос на существование такого сигнала от программы Б.

Ну и бродкастинг соответственно невозможен. Ну, во всяком случае простыми средствами.

windows10 ★★★★★
() автор топика
Ответ на: комментарий от windows10

Программа Б должна уметь обрабатывать запрос на существование сигнала от программы Б? Что это за чушь? И что за программа В? Она подписывалась на сообщения или нет?

И зачем ты переиспользуешь стандартные термины в каком-то необычном смысле? Сигнал это SIGINT SIGKILL SIGTERM итд.

Ну и бродкастинг соответственно невозможен. Ну, во всяком случае простыми средствами.

Чтобы делать бродкастинг и не терять сообщения, обязательно надо знать список тех кто хочет их принять. Только в случае сокетов это будет просто массив сокетов куда надо разослать и забыть, а в случае фс тебе придётся реализовывать протокол подписок, ожидания приёма и подтверждения приёма. Пока все желающие не подтвердят что они твое сообщение прочитали, записывать на его место что-то другое нельзя. А если вообще никогда не записывать - то тебе придётся бесконечно удлинять файл с очередью.

firkax ★★★★★
()
Ответ на: комментарий от windows10

dbus - усложняет, потому что в отличие от того же сокета оперирует не строкой (пардон, набором байтов), а своими неповторимыми костылями.

Среди его типов есть строка. Можешь в неё свой JSON складывать. Но в большинстве случаев проще использовать типы dbus, чем неповторимые костыли JSON.

monk ★★★★★
()
Ответ на: комментарий от monk

Среди его типов есть строка. Можешь в неё свой JSON складывать. Но в большинстве случаев проще использовать типы dbus, чем неповторимые костыли JSON.

Нет, не проще.

Проще - это когда отсылающий использует send(), а принимающий receive(). Как с сокетами, ага.

Но когда у тебя для тривиальной передачи 10 букв листинг на пол-экрана - это ни разу не проще, это оверхед.

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

windows10 ★★★★★
() автор топика