LINUX.ORG.RU

IPC события в одном потоке

 ,


0

2

Смеркалось.

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

Мне не нравится что во всех случаях, кроме сигналов, чтение – забота принимающего сигнал: то есть мне надо либо сидеть в блокировке и ждать сообщения (это не то что мне нужно, мне нужно чтоб программа работала все время) либо заводить отдельный тред и сидеть в блокировке там, а когда придет сообщение – звать уже колбек (это будет план БЭ, хочу поспрашать нет ли чего проще/дешевле). А сигналы мне не нравятся потому что пользовательских всего два, а привязать к ним данные – это надо отдельную песню городить ( ну типа по сигналу, например, выгребать сообщение из очереди )

В общем, как эксперты по всему решают эту проблему? Мож есть какая общеизвестная либа или как обычно зоопарк? Нужно для сей на сабжевую ОС, само собой. Предалгайте!

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

это тебе s6 посмотреть нужно, там то о чем ты догадываешься уже реализовано

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

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

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

А как через память передать событие?

Так же, как и в рамках 1 процесса: через condition variable, см. pthread_condattr_setpshared. Но лучше через eventfd, чтобы можно было в poll интегрировать.

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

Можно вообще мультикаст сокет читать. Чем не общая шина.

Хм. А странно что я об этом не подумал. И никто не предложил до тебя. Это ж может и сгодиться.

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

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

Ненененене. Если придется все это колхозить – то возьму готовое. Я буду делать сам только если оно сделается «в два действия», а если придется прям систему изобретать – то вероятность что ятам накосячу стремиться к единице и чем свое полгода отлаживать проще уже готовое взять,и его поотлаживать в случае чего.

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

Так же, как и в рамках 1 процесса: через condition variable, см. pthread_condattr_setpshared.

А как это можно не для потоков, но для процессов заюзать?

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

A fifodir is a rendez-vous point between the notifier of certain events and its listeners. It is implemented via a directory in the filesystem. No data is stored; it is appropriate to create fifodirs in a RAM filesystem.

Хм… Навскидку как раз то что я собрался изобретать. Ух как посмотрю примеры завтра – держись задача!

(спасибо за ссылку, я сам не осилил нагуглить )

pihter ★★★★★
() автор топика
Последнее исправление: pihter (всего исправлений: 1)

сокеты юниксовые

Это.

Еще пайпы.

Или вообще это. И мультиплексирование ввода-вывода, т.е. epoll, который тут рядом мсьи советовали. Если проблема мсье решается этим — остальное, включая «отдельные треды», оверкилл.

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

И никто не предложил до тебя

Потому что админы могут забанить за флуд в сетке :) Так-то можешь хоть свой ARP изобретать :)

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

Ух как посмотрю примеры завтра – держись задача!

Вот пол треда тебе советуют ZMQ, а ты кидаешься на непойми что. Ты сделай поиск по тому же гитхабу/гуглу/яндексу и сравни, что чаще используют. Тем более, что тебе надо в «прод». ZMQ решает типовые задачи межпроцессорного общения на минимально необходимом уровне (гарантированный разбор на сообщения, разные транспорты, разные модели общения, переподключение, poll). Т.е. ZMQ - это сокеты на стеройдах и без головной боли. Ты элементарно PUB/SUB модель проверь с перезапусками обоих сторон. Плюс документация, статьи, библиотеки под разные ЯП. Уходить за его рамки стоит только, если реально понял что ZMQ недостаточно или он не применим.

Так, например, MQTT любят в IoT за его малые требования к клиенту, который спокойно может крутится на всяких STM-ках. Одно сетевое соединение для общения со всеми.

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

Вот пол треда тебе советуют ZMQ

и он у меня в списке на попробовать: я не тороплюсь, спокойно могу выбрать

ходить за его рамки стоит только, если реально понял что ZMQ недостаточно или он не применим.

а точно не излишен? я им не пользовался, но много слышал – надо посмотреть

я затем и спрашиваю чтоб людей послушать. Вот ты убедителен, советуешь – посмотрю

Спасибо

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

Общая память, а в ней lock-free структура данных, писатель и читатель не блокируют друг друга

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

А тогда внутренний цензор всех одергивает «И... зачем мультикаст?» :)

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

Вот пол треда тебе советуют ZMQ

и он у меня в списке на попробовать: я не тороплюсь, спокойно могу выбрать

Посмотри еще на nanomsg (https://nanomsg.org) от Martin Sustrik - одного из авторов ZeroMQ

sigurd ★★★★★
()
Последнее исправление: sigurd (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Ты так говоришь, как-будто это плохо :)

faq2
()
Ответ на: комментарий от rupert

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

Из минусов тащить именно бустовую реализацию - речь вроде как в основном про C, а вот для C я не помню таких хороших библиотек для работы с разделяемой памятью.

Ещё момент - судя по задачам автора, ему и правда скорее нужен обычный брокер сообщений через петлю, начиная от D-Bus заканчивая zmq, а какую-то экстремальную эффективность, он это так, для красного словца приплёл, и например полностью собирать стек синхронизации на C для его задач - точно оверкилл.

faq2
()
Ответ на: комментарий от pihter

Что нужно понять про пинание «другого процесса». Нету такого понятия.

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

Выбор у тебя есть только где он будет спрятан в ОС или в твоём коде, но на практике использовать цикл обработки ОС (аля epoll) вне своего цикла обработки событий всё равно не выйдет для хоть сколько-нибудь отдалённого от hello world случая.

faq2
()
Последнее исправление: faq2 (всего исправлений: 1)

я за «читать пайп в отдельном треде», потому что а что ещё тут можно придумать? Если нужен строго один тред, то крутить полезную работу как-нибудь в цикле, и там же периодически интересоваться состоянием пайпа с O_NONBLOCK.

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

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

я за «читать пайп в отдельном треде»

хвастаюсь:

#include <stdio.h>
#include <unistd.h>
#include <string>

#include "ipc_events.h"

int main_loop_running = 1;

void ipc_events_callback( std::string event ) {
  printf( "receiving event:%s\n", event.c_str() );
  if ( event == "stop" ) {
    main_loop_running = 0;
  }
}

int main( int argc, char** argv ) {
  ipc_events_start_listening( "my_program", &ipc_events_callback );

  while( main_loop_running ) {
    printf( "heart beat\n" );
    sleep(10);
  }

  ipc_events_stop_listening();

  return 0;
}

работает – как молоток, использовать – проще не придумать. Реализация – 70 строчек.

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

единственное что если слать ему в пайп эти события быстрее, чем он выгребать будет – то при переполнении пайпа в посылающую программу прилетает какой-то карающий сигнал. Но это все равно не мой случай

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

Обожаю треды :)

Так она ж ставится только в одном месте, кто ее может поломать? )

ЗЫ: я уж думал в этих трех строчках никто не докопается :)

pihter ★★★★★
() автор топика
Последнее исправление: pihter (всего исправлений: 1)
Ответ на: комментарий от pihter

работает – как молоток, использовать – проще не придумать. Реализация – 70 строчек.

Так это пока ты в другие треды ничего не передаёшь :) Ну.. либо довольно тонко.

А ещё - ты обещал C! А суёшь кресты.

faq2
()

Асинхронный ввод/вывод на базе select()/poll()/epoll() прекрасно эту задачу решает. Причем я считаю лучшим вариант на основе unix socket, так как сервер четко видит, что к нему подключаются и каждым можно общаться индивидуально.

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

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

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

Так она ж ставится только в одном месте, кто ее может поломать? )

так а читается же в другом! )

в одном потоке ты пишешь новое значение, а в это время читатель из другого потока читает что?

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

А ещё - ты обещал C! А суёшь кресты.

Реализация сишная. Ну местами есть std::string только, но ТОЛЬКО он из плюсов чтоб со строками возни меньше, пока тещщу. К проду перепишу на си, если подход оправдается

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

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

А я и не ищу халявы: я ищу чужого опыта. Как ты видишь по треду мне много накидали идей, много насоветовали, есть разные мнения. Ни ЛОР, а прям – золото

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

// я, конечно, мажусь уже

но! на сколько битов, по-твоему, отличается int 0 и int 1? :) нешто запись одного бита уже не атомарна в наше время…

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

Мне и придётся. А что там поддерживать? Там 4 функции общим весом в 70 строк

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

Это потому, что ты спишь 10 секунд на читателе

Спит-то главный тред. Вспомогательных в это время висит на блокирующем чтении из пайпа. Во время этого слип 10 100500 сообщений обрабатывается

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

В том цикле где слип ниче не делается. Как говорится - очки протри!)

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

нешто запись одного бита уже не атомарна в наше время…

казалось бы

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

на этот счет в ядре есть

#include <asm/bitops.h>

void set_bit(int nr, void *a); // Set the bit number nr in value pointed by a
void clear_bit(int nr, void *a); // Clear the bit number nr in value pointed by a
void change_bit(int nr, void *a); // Toggle the bit at position nr

полюбопытствуй на досуге

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

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

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

если вы таком-же стиле и прочие процессы на localhost делаете, то может незаметно наступить ССЗБ :-)

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

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

Это потому, что ты спишь 10 секунд на читателе

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

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

Ну, там хоть асинхронка в треде?

Какая ещё асинхронка?

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

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

Никаких очередей, в лоб зовёт вот этот колбек отдавая все данные

Какой Нафиг контекст? Речь максимум о десятке сообщений в секунду. Время работы глазами не видно - значит пойдёт!)

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

/ и кстати, заблуждение считать что если таким образом перенести чтение в отдельный поток то реакция станет быстрее

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

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

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

«выгребать и отдавать» часто оказывается хуже чем читать сразу в основном треде. вызовы epoll/select и абстракции async/await не просто так сделаны

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

«выгребать и отдавать» часто оказывается хуже чем читать сразу в основном треде

Я честно пытался эту мысль до ТС донести - «лишние» context switches ничего не принесут кроме дополнительных задержек и геморроя. Я бы так не делал. Лучше уж «по старинке»…

bugfixer ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.