Модераторы: xvr

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [pipe] возможность прервать блокирующую операцию 
:(
    Опции темы
cupper
Дата 15.3.2012, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: нет
Всего: 1



Пытаюсь реализовать корректное завершение потока заблокированного на операции с pipe'ом.

Первый вариант работа в лоб
Код

mkfifo(FIFO_FILE, 0666)
handle_ = open(FIFO_FILE, O_READONLY);

заблокируется на операции open до тех пор пока другой процесс не откроет pipe на запись. Прервать эту операцию на вряд ли получится. Я не нашел способа.

Второй вариант, используем неблокирующий режим
Код

mkfifo(FIFO_FILE, 0666)
handle_ = open(FIFO_FILE, O_RDWR | O_NONBLOCK);

int flags;
if ((flags = fcntl(handle_, F_GETFL, 0)) < 0) printf("ERROR: fcntl get\n");
flags &= ~O_NONBLOCK;
if (fcntl(handle_, F_SETFL, flags) < 0) printf("ERROR: fcntl set\n");

fd_set rfds;
FD_ZERO(&rfds);
FD_SET(handle_, &rfds);
if(select(handle_ + 1, NULL, &rfds, &rfds, NULL) == -1)

Пояснение 1: после того как мы "открыли" pipe переводим его в блокирующий режим иначе каждая наша операция будет сразу возвращаться управление.
Пояснение 2: используем select, но мы не можем использовать его для операции read так как она возвращает 0 на еще не открытом pipe, поэтому открываем pipe в оба режима, и блокируемся на операции write.

Я было надеялся что операция write прервется если мы сделаем close(), но она не прерывается. Так же не появляется исключительная ситуация (для которой я попробовал установить 4 параметр select).

Долго и усердно пытался найти как прервать select. Не нашел. 
Вариант использования pselect плохой, так как я не могу послать сигнал в поток он шлется в процесс.

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

Излазил весь интернет, все что нашел сведено в коде выше.

PS. хммм, обнаружил такую функцию pthread_kill... неужели в лине можно послать сигнал конкретному потоку ?

Это сообщение отредактировал(а) cupper - 15.3.2012, 23:26
PM MAIL   Вверх
xvr
Дата 16.3.2012, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(cupper @  15.3.2012,  22:33 Найти цитируемый пост)
Долго и усердно пытался найти как прервать select. Не нашел. 

Открыть еще один pipe (анонимный) и подать его 2м handle'ом в select. Ну и записать в него что нибудь, что бы прервать select.
Еще можно использовать eventfd вместо 2го пайпа (если у вас ядро >  2.6.22)

Цитата(cupper @  15.3.2012,  22:33 Найти цитируемый пост)
используем select, но мы не можем использовать его для операции read так как она возвращает 0 на еще не открытом pipe,

Попробуйте poll или epoll

PM MAIL   Вверх
cupper
Дата 16.3.2012, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: нет
Всего: 1



Цитата(xvr @ 16.3.2012,  11:47)
Открыть еще один pipe (анонимный) и подать его 2м handle'ом в select. Ну и записать в него что нибудь, что бы прервать select.

Ну это по сути ненужное усложнение способа открыть пайп и записать туда что нибудь. 

Цитата(xvr @ 16.3.2012,  11:47)

Попробуйте poll или epoll

И что изменится ? Повисну в нем так же как и в select. Уточните пожалуйста, что вы имели в виду под этим, я может вас не понял.


Это сообщение отредактировал(а) cupper - 16.3.2012, 20:54
PM MAIL   Вверх
Fynivx
Дата 16.3.2012, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



А нельзя использовать стандартные средства плюсов? condition_variable, например?
Там есть метод, который может ожидать сигнала определенное время. А во втором процессе - посылать сигнал после открытия.

Потоки уже стандартизированы в C++...
PM MAIL   Вверх
cupper
Дата 16.3.2012, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: нет
Всего: 1



Цитата(Fynivx @ 16.3.2012,  22:49)
А нельзя использовать стандартные средства плюсов? condition_variable, например?
Там есть метод, который может ожидать сигнала определенное время. А во втором процессе - посылать сигнал после открытия.

Потоки уже стандартизированы в C++...

в винде я так и сделал, там есть Event и есть WaitForMultipleObject.
В linux аналога нету. Есть select который умеет проверять что следующая операция (чтения, записи) не будет блокирующая. Есть pselect который еще умеет ждать сигнал (но сигналы то шлются все тредам, хотя есть pthread_kill но его работа для меня пока не очень ясна, да и сигнал это не средство синхронизации).

Использовать TimeOut вообще плохая затея. 

Но я не понял как вы предлагаете скрестить condition_variable и блокирующую open или write ? Это как раз то что нужно, вот только я не знаю возможно ли такое smile
PM MAIL   Вверх
Fynivx
Дата 17.3.2012, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



Цитата(cupper @  16.3.2012,  23:12 Найти цитируемый пост)
как вы предлагаете скрестить condition_variable и блокирующую open или write ?

Блокирующий - не знаю. А с неблокирующим возможно. По крайней мере, я представляю примерно так:

Первый процесс создает и открывает очередь в неблокирующем режиме, после чего вызывает wait с таймаутом. Это для того, чтобы, если второй процесс так и не откроет соединение, первый не завис в бесконечном ожидании.
Если сообщение было получено, начинается обмен. Если нет - очередь закрывается.

А второй, опять же, открывает очередь, и посылает первому сообщение об открытии через notify.
Как-то так.

notify_one посылает сигнал одному процессу, notify_all - всем ожидающим.

Вообще можно организовать очередь любого типа нативными средствами. По крайней мере, я бы так сделал. И никакой привязки к операционке не будет. Хм... Или у Вас привязка к C а не к C++?


А можете описать задачу взаимодействия процессов в целом? Может, что проще придумается и без хэдеров windows и pthreads.
PM MAIL   Вверх
svlary
Дата 17.3.2012, 06:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата(cupper @  15.3.2012,  22:33 Найти цитируемый пост)
Прервать эту операцию на вряд ли получится. 

    А зачем ее прерывать ? Смысл pipe как раз и заключается в том, что СЕРВЕР должен повиснуть до тех пор, пока КЛИЕНТ не положит 
свое сообщение в pipe.  Главная мысль : pipe должны использовать два (!) процесса. И один из них должен постоянно 
висеть на чтении. Проще говоря - ждать прихода сообщения. И это абсолютно  нормальная логика клиент/серверных технологий.
Зачем ее ломать изобретая деревянные велосипеды на треугольных колесах - я не понимаю.

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


Код

Главный процесс                                     Подчиненный процесс

// Создаем pipe
mkfifo(...)

// Запускаем клиента
fork(...)
                                                                // После подготовки, клиент хочет отправить сообщение серверу:
                                                                fw = open(..., O_WRONLY); // Клиент повис - ждет сервера


// Управление передается в процесс сервера
fr = open (..., O_RDONLY);   // Вот и встретились два одиночества...

// Серовер повис на ожидании сообщения
  read(fr,...);

                                                                 // Управление вернулось в клиент - он пишет сообщение :
                                                                write(fw,...); // И занимается своими делами

// Сервер соскакивает с read и обрабатывает поступившую команду.
proccess_cmd(...);

// И возвращается в начало ЦИКЛА чтения сообщений




Для ознакомления с классикой программирования под Unix/Linux рекомендую хотя бы : Марк Дж Рочкинд. "Программирование для UNIX". 

PM MAIL   Вверх
Fynivx
Дата 17.3.2012, 07:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 13.8.2011

Репутация: нет
Всего: 1



Цитата(svlary @  17.3.2012,  06:21 Найти цитируемый пост)
А зачем ее прерывать ?

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

Но я, честно говоря, не могу представить ситуацию, где их использование выгоднее)

Добавлено через 3 минуты и 31 секунду
Даже для двух совершенно разных модулей, написанных на разных языках, можно сообразить шаред-мемори через dll'ку)
PM MAIL   Вверх
rsm
Дата 17.3.2012, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 999
Регистрация: 16.3.2005

Репутация: 3
Всего: 62



Цитата(cupper @  16.3.2012,  00:33 Найти цитируемый пост)
Долго и усердно пытался найти как прервать select. Не нашел

Как один из самых элементарных вариантов:
а) создаём маску сигналов, в которой заблокировано всё;
б) назначаем эту маску процессу;
в) удаляем из маски какой-то сигнал, к примеру SIGUSR1;
г) висим на pselect;
д) когда надо, сами себе оправляем заранее определённый сигнал (SIGUSR1);
е) pselect завершается по прерванному системному вызову;
Вариант другой, более годный: вынести обработку сигналов в отдельный поток. Делать такое необходимо, если в программе используется таймер, т.к. все блокируемые системные вызовы будут прерываться по каждому тику таймера.
Оба варианта хорошо описаны у Стивенса.
PM MAIL   Вверх
xvr
Дата 17.3.2012, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(cupper @  16.3.2012,  20:52 Найти цитируемый пост)
Ну это по сути ненужное усложнение способа открыть пайп и записать туда что нибудь. 

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

Цитата(cupper @  16.3.2012,  20:52 Найти цитируемый пост)
И что изменится ? Повисну в нем так же как и в select. Уточните пожалуйста, что вы имели в виду под этим, я может вас не понял.

У него больше возможностей по вариантам ожидания. Возможно какая то из них может сработать например на банальное закрытие handle'а

PM MAIL   Вверх
cupper
Дата 17.3.2012, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: нет
Всего: 1



Цитата(svlary @ 17.3.2012,  06:21)
А зачем ее прерывать ? Смысл pipe как раз и заключается в том, что СЕРВЕР должен повиснуть до тех пор, пока КЛИЕНТ не положит свое сообщение в pipe.

мысли глубже. А как вы сервер выключать будете ? kill -9 ? или pthread_abort ?

Цитата(Fynivx @ 17.3.2012)

Первый процесс создает и открывает...
А второй...

а второго нету, pipe открывает из ОС.


Цитата(rsm @ 17.3.2012)

а) создаём маску сигналов, в которой заблокировано всё;
б) назначаем эту маску процессу;
в) удаляем из маски какой-то сигнал, к примеру SIGUSR1;

Вы выше мои изливания душевных мук на счет сигналов и синхронизации читали ?

Ну по сути как не крутись есть только два способа
* pselect + signal
* открыть pipe для того что бы завершить поток ожидающий его.

Второй явно безопаснее и проще.

Это сообщение отредактировал(а) cupper - 17.3.2012, 10:48
PM MAIL   Вверх
rsm
Дата 17.3.2012, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 999
Регистрация: 16.3.2005

Репутация: 3
Всего: 62



Цитата(cupper @  17.3.2012,  12:37 Найти цитируемый пост)
Вы выше мои изливания душевных мук на счет сигналов и синхронизации читали ?

Читал. Не проникся, т.к. не смог обнаружить признаков понимания работы сигналов и их воздействия на системные вызовы, потоки и процессы. Потому и посоветовал заглянуть в книжку.
PM MAIL   Вверх
cupper
Дата 17.3.2012, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: нет
Всего: 1



Цитата(rsm @ 17.3.2012,  16:19)
Цитата(cupper @  17.3.2012,  12:37 Найти цитируемый пост)
Вы выше мои изливания душевных мук на счет сигналов и синхронизации читали ?

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

убедили. Да я действительно не понимаю как работают сигнала, и это то из за чего я не хотел их использовать. Загляну в книжку, проникнусь. 
PM MAIL   Вверх
rsm
Дата 17.3.2012, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 999
Регистрация: 16.3.2005

Репутация: 3
Всего: 62



Накатал на досуге пример (в аттаче). Для его полного понимания потребуется знать матчасть, ибо объяснять всё "от Адама" не хватит никакого форума smile
P.S. Извиняюсь за архив в zip - как выяснилось, родимый tgz не поддерживается для аплоада smile

Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  pipe_example.zip 4,47 Kb
PM MAIL   Вверх
svlary
Дата 18.3.2012, 05:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 207
Регистрация: 8.9.2009

Репутация: 4
Всего: 4



Цитата(Fynivx @  17.3.2012,  07:04 Найти цитируемый пост)
куча неконтролируемых сверху процессов работают с одной областью памяти

 О том, что использование COMMON переменных - весьма опасная практика, догадались еще програмисты на fortran-е 40 лет назад... smile Неужели ничего в замен придумать невозможно ?!

[/quote]
нужно предусмотреть ситуацию, когда один из них внезапно сломается.[/quote]

Специально для этого придуманы сигналы SIGPIPE и SIGCHILD. Надо просто написать обработчик соответствующих сигналов.

Добавлено через 10 минут и 48 секунд
Цитата(cupper @  17.3.2012,  10:37 Найти цитируемый пост)
 А как вы сервер выключать будете ?

  Для этого в ОС Linux существует стандартная методика. Например, сервер MySQL гасится командой :

Код

/etc/init.d/mysql stop


Разработчики любых других серверов ОБЯЗАНЫ предоставить системе аналогичные средства.

Цитата
pipe открывает из ОС.

   Это - как ?! 
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.1138 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.