Передать произвольные данные в уже запущенную программу. (Нужна коллективная мысль.)

Модератор: Модераторы разделов

Аватара пользователя
Zeus
Сообщения: 694

Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

Есть программа, написанная мною (т.е. я о ней всё знаю и, в принципе, могу добавить какую угодно функциональность), но запущенная в системе когда-то и кем-то. Я могу узнать её PID.
Есть потребность передать ей, ну допустим, символьную строку или число (хотя число тоже можно строкой передать).
Как это правильнее, логичнее, разумнее, переносимее (продолжить по необходимости) сделать?
Совсем замечательно - если это можно из bash'а сделать.
Т.е. не писать отдельную программу, а какой-нибудь echo или ещё что-нибудь подобное использовать.
Спасибо сказали:
Аватара пользователя
Omnifarious
Сообщения: 119
ОС: Gentoo x86_64

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Omnifarious »

В свое время мы писали программку, которая передавала файлы с помощью сигналов SIGUSR1 и SIGUSR2. В принципе так можно передавать любые двоичные данные, лишь бы клиентская программа их принимала.
There is more than one way to do it
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

Omnifarious писал(а): ↑
24.03.2006 10:26
В свое время мы писали программку, которая передавала файлы с помощью сигналов SIGUSR1 и SIGUSR2. В принципе так можно передавать любые двоичные данные, лишь бы клиентская программа их принимала.

А как можно с помощью сигнала (события т.е.?) передать файл? :mellow:
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

Zeus писал(а): ↑
24.03.2006 10:18
Есть программа, написанная мною (т.е. я о ней всё знаю и, в принципе, могу добавить какую угодно функциональность), но запущенная в системе когда-то и кем-то. Я могу узнать её PID.
Есть потребность передать ей, ну допустим, символьную строку или число (хотя число тоже можно строкой передать).
Как это правильнее, логичнее, разумнее, переносимее (продолжить по необходимости) сделать?
Совсем замечательно - если это можно из bash'а сделать.
Т.е. не писать отдельную программу, а какой-нибудь echo или ещё что-нибудь подобное использовать.


Google -> Interprocess Communications :) Ну а вообще для переносимости и масштабируемости я бы воспользовался сокетами.
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
JaGoTerr
Сообщения: 380

Re: Передать произвольные данные в уже запущенную программу.

Сообщение JaGoTerr »

$ mkfifo /tmp/my_fifo_file
$ echo "what u want" > /tmp/my_fifo_file
Ну а уж читать fifo-файл в программе больщого ума не надо.

man fifo, короче говоря.
Спасибо сказали:
Аватара пользователя
Omnifarious
Сообщения: 119
ОС: Gentoo x86_64

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Omnifarious »

Zeus писал(а): ↑
24.03.2006 10:29
А как можно с помощью сигнала (события т.е.?) передать файл? :mellow:


По битам. Пришел SIGUSR1 - значит 0, SIGUSR2 - 1. Так собираешь потихоньку байтики - получается файл. Главное про синхронизацию передающей и принимающей стророны не забывать. Работает очень медленно :), но по мелочам(строчку там передать) - не напрягает.

P.S. Но сокеты конечно проще и логичнее использовать.
There is more than one way to do it
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

Omnifarious писал(а): ↑
24.03.2006 11:13
По битам. Пришел SIGUSR1 - значит 0, SIGUSR2 - 1. Так собираешь потихоньку байтики - получается файл. Главное про синхронизацию передающей и принимающей стророны не забывать. Работает очень медленно :), но по мелочам(строчку там передать) - не напрягает.

P.S. Но сокеты конечно проще и логичнее использовать.


Ну вы даете! Пишите еще :)

З.Ы. Я даже из своего предыдущего поста убрал, что никак передать через сигналы файл нельзя :) Теперь я знаю, что можно :D
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Omnifarious
Сообщения: 119
ОС: Gentoo x86_64

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Omnifarious »

d_Sun писал(а): ↑
24.03.2006 11:18
Ну вы даете! Пишите еще :)

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


Это была задача преподавателя по информатике. Любил он нетривиальные решения :)
There is more than one way to do it
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

("(Prentice Hall 2003) - Unix Systems Programming. Communication @ Concurrency, and Threads") писал(а):The usefulness of signal handlers is limited by the inability to pass values to them. This capability has been added to the POSIX:RTS and POSIX:XSI Extensions, which can use the alternative sa_sigaction field of the struct sigaction structure to specify a handler.


Во как! Таки можно с сигналами данные передавать! ( при указанных выше условиях ессесно :) )

З.Ы. Если кому интересно приведу более детальное описание как это сделать, но на инглише! Переводить влом :)
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

Ну что ж, мнение народа понятно :)
Спасибо всем.

Omnifarious писал(а): ↑
24.03.2006 11:13
Zeus писал(а): ↑
24.03.2006 10:29

А как можно с помощью сигнала (события т.е.?) передать файл? :mellow:


По битам. Пришел SIGUSR1 - значит 0, SIGUSR2 - 1. Так собираешь потихоньку байтики - получается файл. Главное про синхронизацию передающей и принимающей стророны не забывать. Работает очень медленно :), но по мелочам(строчку там передать) - не напрягает.

P.S. Но сокеты конечно проще и логичнее использовать.

Нихрена себе изврат какой! :blink:

:)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

JaGoTerr писал(а): ↑
24.03.2006 11:11
$ mkfifo /tmp/my_fifo_file
$ echo "what u want" > /tmp/my_fifo_file
Ну а уж читать fifo-файл в программе больщого ума не надо.

man fifo, короче говоря.

Спасибо за наводку :)
Но в процессе экспериментов появилась ещё проблема:
1. Сделал я fifo
2. Открыл её на чтение в программе.
3. В бесконечном цикле читаю файл - поток заблокировался на read.
3. Кинул из консоли туда сообщение echo'ом.
4. Оно прочиталось.
5. И на следующей итерации цикла read уже не блокируется, а бесконечно выдаёт одну и ту же строку - ту самую, первую которую я ему кинул.

Пробовал std::ifstream использовать - тоже блокируется только один раз, а потом - одно и то же выдаёт.
Пробовал select - тоже самое. Один раз блокирует, а потом постоянно возвращает что есть дескрипторы для чтения.

В книге (не помню название - довольно детская какая-то) сказано, что ядро заблокирует поток при ОТКРЫТИИ fifo на чтение, пока его кто-то не откроет на запись. Ну а вообще - типа работайте как с обычным файлом.

А вот у меня при ОТКРЫТИИ ничего не блокируется, блокируется при чтении данных.
Но вот дальше - работать "как с обычным файлом" что-то не получается.
Спасибо сказали:
Аватара пользователя
flook
Сообщения: 585
Статус: Просто flook

Re: Передать произвольные данные в уже запущенную программу.

Сообщение flook »

Zeus писал(а): ↑
29.03.2006 11:47
1. Сделал я fifo
2. Открыл её на чтение в программе.
3. В бесконечном цикле читаю файл - поток заблокировался на read.
3. Кинул из консоли туда сообщение echo'ом.
4. Оно прочиталось.
5. И на следующей итерации цикла read уже не блокируется, а бесконечно выдаёт одну и ту же строку - ту самую, первую которую я ему кинул.

сорс в студию.
$ mkfifo x
$ tail -f x
в другом терминале
$ echo 1 > x
$ echo 2 > x
$ echo 3 > x
все прекрасно пашет. наверняка ошибка в программе.
В каждом из нас спит гений... и с каждым днем все крепче...
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

flook писал(а): ↑
29.03.2006 14:52
Zeus писал(а): ↑
29.03.2006 11:47

1. Сделал я fifo
2. Открыл её на чтение в программе.
3. В бесконечном цикле читаю файл - поток заблокировался на read.
3. Кинул из консоли туда сообщение echo'ом.
4. Оно прочиталось.
5. И на следующей итерации цикла read уже не блокируется, а бесконечно выдаёт одну и ту же строку - ту самую, первую которую я ему кинул.

сорс в студию.
$ mkfifo x
$ tail -f x
в другом терминале
$ echo 1 > x
$ echo 2 > x
$ echo 3 > x
все прекрасно пашет. наверняка ошибка в программе.

Исходник - дома. Позже выложу.
bash'евский пример из той же книжки - тоже работает так как ожидалось.
А вот мой C'шный код - не хочет.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

flook писал(а): ↑
29.03.2006 14:52
сорс в студию.


Код такой:

Код: Выделить всё

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <fstream>

#define FOREVER while (1)
//#define FOREVER

//#define READ_C
#define STREAM_CPP


int
main ()
{
#ifdef READ_C
    int fd;
    fd = open ("fifo", O_RDONLY);
    char buf[100];
    FOREVER
    {
    memset (buf,0,100);
    read (fd, buf, 100);
    std::cout << "buf = [" << buf << "]" << std::endl;
    }
#endif

#ifdef STREAM_CPP
    std::ifstream fifo ("fifo");
    std::string str;
    FOREVER
    {
    str = "";
    fifo >> str;
    std::cout << "str=[" << str << "]" << std::endl;
    }
#endif



    return 0;
};

Компилю просто: g++ temp.cpp

Если не "обнулять" buf и str, то в следующей итерации цикла их значение равно предыдущему.
Т.е. получается read и операция чтения из потока их не изменяют, сразу возвращая управление.
Спасибо сказали:
Аватара пользователя
flook
Сообщения: 585
Статус: Просто flook

Re: Передать произвольные данные в уже запущенную программу.

Сообщение flook »

1. А ошибки проверять?
2. Когда делается echo 1 > fifo то программа видит следующее:
1. блокируется на open пока echo не сделает open
2. read - видит 1
3. read - EOF, так как echo закрывает файл - после этого всегда будет read возвращать 0.
3. Учите матчасть :)
В каждом из нас спит гений... и с каждым днем все крепче...
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

flook писал(а): ↑
30.03.2006 11:39
1. А ошибки проверять?

Ну так, думал тестовый пример - чего там проверять-то? :unsure:

2. Когда делается echo 1 > fifo то программа видит следующее:
1. блокируется на open пока echo не сделает open

Вот сейчас поправил "эксперимент" - действительно он на open'е блокируется (и на конструкторе ifstream), а не на read, как мне раньше казалось :)

2. read - видит 1

Не 1, а число реально полученных байт. Но это не важно.

3. read - EOF, так как echo закрывает файл - после этого всегда будет read возвращать 0.

Для EOF вроде отдельная функция есть, но это тоже не важно.
Вот эта непонятная зависимость - что ТАМ закрывают файл, а у меня тут EOF - вот к этому я не был готов.

3. Учите матчасть :)

Учим. Только не нашёл нормального объяснения работе с fifo в дистрибуте.
А к Инету в тот момент доступ не имел.
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

int fd;
int dummy;
fd = open ("/home/andreyp/fifo", O_RDONLY );
dummy = open ("/home/andreyp/fifo", O_WRONLY );


fifo открой еще и на запись, и будет тебе сЧастЯ... Зачем? flook уже сказал - учите мат часть :)

З.Ы. А за FOREVER спасибо - плакалЪ :)
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

d_Sun писал(а): ↑
30.03.2006 12:05

int fd;
int dummy;
fd = open ("/home/andreyp/fifo", O_RDONLY );
dummy = open ("/home/andreyp/fifo", O_WRONLY );

fifo открой еще и на запись, и будет тебе сЧастЯ... Зачем? flook уже сказал - учите мат часть :)

Спасибо, попробую.
Еще можно, наверное, просто открытие очереди на чтение внести в цикл?

З.Ы. А за FOREVER спасибо - плакалЪ :)

Пожалуйста. Я думал это известная тема :)
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

Zeus писал(а): ↑
30.03.2006 12:49
Еще можно, наверное, просто открытие очереди на чтение внести в цикл?


Можно и так, только закрытие туда же внеси. Но это, что называется "через Ж" :) Лучше делать как я выше писал.
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

d_Sun писал(а): ↑
30.03.2006 14:14
Zeus писал(а): ↑
30.03.2006 12:49

Еще можно, наверное, просто открытие очереди на чтение внести в цикл?


Можно и так, только закрытие туда же внеси. Но это, что называется "через Ж" :) Лучше делать как я выше писал.

Спасибо.
Правда в потоковой версии добавление std::ofstream не помогло.
Как, впрочем, и открытие очереди на чтение.
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

Zeus писал(а): ↑
30.03.2006 16:39
Правда в потоковой версии добавление std::ofstream не помогло.
Как, впрочем, и открытие очереди на чтение.


Опять же - код в студию...
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

d_Sun писал(а): ↑
30.03.2006 17:07
Zeus писал(а): ↑
30.03.2006 16:39

Правда в потоковой версии добавление std::ofstream не помогло.
Как, впрочем, и открытие очереди на чтение.


Опять же - код в студию...


Да, в общем-то, дополнения небольшие:

Код: Выделить всё

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <fstream>

#define FOREVER while (1)
//#define FOREVER

#define READ_C
//#define STREAM_CPP


int
main ()
{
#ifdef READ_C
    int fd, fd1;
    fd = open ("fifo", O_RDONLY);
    fd1 = open ("fifo", O_WRONLY);
    std::cout << "Начинаем" << std::endl;
    char buf[100];
    int rd;
    FOREVER
    {
    memset (buf,0,100);
    rd = read (fd, buf, 100);
    std::cout << "buf = [" << buf << "] rd=" << rd << std::endl;
    }
    close (fd);
    close (fd1);
#endif

#ifdef STREAM_CPP
    std::ifstream fifo ("fifo");
    int fd1 = open ("fifo", O_WRONLY);
    std::cout << "Начинаем" << std::endl;
    std::string str;
    FOREVER
    {
    std::cout << "Продолжаем" << std::endl;
    str = "";
    fifo >> str;
    std::cout << "str=[" << str << "]" << std::endl;
    }
    close (fd1);
#endif

    return 0;
};


Ну или в версии STREAM_CPP вместо открытия файла для записи используется

Код: Выделить всё

std::ofstream fifo1 ("fifo");


В обоих случах поток выполнения блокируется на fifo >> str;
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

Zeus писал(а): ↑
30.03.2006 17:19
В обоих случах поток выполнения блокируется на fifo >> str;


И это правильно! Блокируется и ждет данные. А тебе что нужно?
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

d_Sun писал(а): ↑
30.03.2006 17:30
Zeus писал(а): ↑
30.03.2006 17:19

В обоих случах поток выполнения блокируется на fifo >> str;


И это правильно! Блокируется и ждет данные. А тебе что нужно?

Ну так я по эксперименту-то кидаю данные туда из другой консоли echo'ом, только оно так и не разблокируется.
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

Zeus писал(а): ↑
30.03.2006 17:46
Ну так я по эксперименту-то кидаю данные туда из другой консоли echo'ом, только оно так и не разблокируется.


ifstream fifo ("/home/andreyp/fifo");
ofstream ofifi ( "/home/andreyp/fifo" );
string str;
FOREVER
{
str = "";
fifo >> str;
std::cout << "str=[" << str << "]" << std::endl;
}


Вот так работает?
Моя подпись сильно длинная :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

d_Sun писал(а): ↑
30.03.2006 17:49
Zeus писал(а): ↑
30.03.2006 17:46

Ну так я по эксперименту-то кидаю данные туда из другой консоли echo'ом, только оно так и не разблокируется.


ifstream fifo ("/home/andreyp/fifo");
ofstream ofifi ( "/home/andreyp/fifo" );
string str;
FOREVER
{
str = "";
fifo >> str;
std::cout << "str=[" << str << "]" << std::endl;
}


Вот так работает?

Неа :unsure:
Продолжаем в аське.
Если будут результаты - выкладываем.
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Передать произвольные данные в уже запущенную программу.

Сообщение t.t »

(d_Sun @ Mar 30 2006, в 10:05) писал(а):З.Ы. А за FOREVER спасибо - плакалЪ
А фигли? И в книжках такие примеры есть; там, где я видел, правда, было for(;;), но разницы-то?
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
Гарыныч
Сообщения: 202
ОС: Gentoo

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Гарыныч »

А если взять dbus?
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Передать произвольные данные в уже запущенную программу.

Сообщение Zeus »

Zeus писал(а): ↑
30.03.2006 18:09
d_Sun писал(а): ↑
30.03.2006 17:49

Zeus писал(а): ↑
30.03.2006 17:46

Ну так я по эксперименту-то кидаю данные туда из другой консоли echo'ом, только оно так и не разблокируется.


ifstream fifo ("/home/andreyp/fifo");
ofstream ofifi ( "/home/andreyp/fifo" );
string str;
FOREVER
{
str = "";
fifo >> str;
std::cout << "str=[" << str << "]" << std::endl;
}


Вот так работает?

Неа :unsure:
Продолжаем в аське.
Если будут результаты - выкладываем.

Попробовал без ofstream'а перенести ifstream в тело цикла.
Заработало.
Оставил на ночь echo-цикл.
На 206тысячах передачи сообщений через fifo скрипт упал (написал "Broken pipe"), а С++ прога заблокировалась.

Гарыныч писал(а): ↑
31.03.2006 01:36
А если взять dbus?

А это что?
Спасибо сказали:
Аватара пользователя
d_Sun
Сообщения: 291

Re: Передать произвольные данные в уже запущенную программу.

Сообщение d_Sun »

t.t писал(а): ↑
31.03.2006 01:25
А фигли? И в книжках такие примеры есть; там, где я видел, правда, было for(;;), но разницы-то?


Так может все условные операторы всякой [ CENSORED ] позаменяем? Где-то гулял по нету язык программирования ПРЕВЕД... Видели? :) Вы сторонник такого подхода?

З.Ы. Я б за такие FOREVы... :)


Zeus - забей на плюсы :) У меня дома тоже не заработало :) , а твои танцы с бубном

Попробовал без ofstream'а перенести ifstream в тело цикла.
Заработало.
Оставил на ночь echo-цикл.


ни к чему хорошему не приведут. Работай на низком уровне. Ну или оберни в класс эти фифо... ( но опять же пользуй open/read... etc )
Моя подпись сильно длинная :)
Спасибо сказали: