Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/86: Рейтинг темы: голосов - 86, средняя оценка - 4.87
 Аватар для Daki
0 / 0 / 0
Регистрация: 24.10.2009
Сообщений: 16

Перехват Сигнала

28.05.2010, 11:03. Показов 18417. Ответов 58
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Тема работы "Сигналы". Мне дали доп задание: "Один источник посылает сигнал(любой, любым способом). Есть приёмник, который должен принимать эти сигналы. Нужно добавить перехватчик сигналов, и вывести количество перехваченных сигналов, если это получится". Кода нет вообще. Киньте хоть ссылки, где прочитать про эти перехватчики можно, ато я что-то совсем ничего не могу найти.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
28.05.2010, 11:03
Ответы с готовыми решениями:

Перехват сигнала с com/lpt/game порта
Можно ли средсвами .Net перехватить сигнал с com/lpt/game порта? Если да, то как? Заранее спасибо.

Перехват сигнала твоего телефона идущего через модем
В первую очередь, чисто теоретически возможно ли Перехватить сигнал твоего телефона идущего через модем... а в дополнение комп набирает...

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

58
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 14:58
Студворк — интернет-сервис помощи студентам
Таки удалось, запихать. Если кто не видел, то думаю будет интересно прочитать:

Основной текст написал: Yar Tikhiy <yar at comp.chem.msu.su>

Предисловие

Если судить по исходникам популярных программ и обсуждениям Usenet
за последние лет 20, то обработка сигналов Unix -- это игра, в
которой большинство участвует, так и не удосужившись выучить правила.
Программисты привыкли, что если код не засбоит хотя бы один раз,
то он будет работать во всех случаях. Сигналы оказались для них
хорошо замаскированной ловушкой, из которой всем нам предстоит еще
долго выкарабкиваться (о последствиях неаккуратной работы с сигналами
для безопасности см. статью "Delivering Signals for Fun and Profit":
http://www.bindview.com/Servic... ignals.cfm).

Академическое сообщество пользователей Unix всегда поощряло
"экспериментальный" стиль программирования, когда во главу угла
ставится сам факт реализации той или иной возможности, а не качество
решения. В 1986 году даже почтенный Chris Torek допускал высказывания
вроде этого: "Хотя вызывать exit(3) из обработчика сигнала не вполне
надежно, на практике это не создает никаких проблем". Впрочем, сам
мистер Torek отрекся от подобной ереси к началу 1990-х; зато
недостатка в программистах, обрабатывающих сигналы по принципу
"авось пронесет", и книгах, дающих сомнительные советы, не ощущается
до сих пор.

Что удивительно в такой ситуации, правила "игры в сигналы" на самом
деле весьма просты. Поэтому хотелось бы их четко сформулировать и
указать на основные следствия из них. Для начала я попытаюсь это
сделать для случая традиционных сигналов POSIX в однонитевой среде.
Комментарии и дополнения приветствуются.

ПРАВИЛА ИГРЫ В СИГHАЛЫ UNIX

Правило 1

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

1. Если сигнал игнорируется, то он не оказывает никакого воздействия
на процесс. В частности, не прерываются по EINTR прерываемые
операции. (Исключение - в системах с kqueue, если установить
прослушивание сигнала (EVFILT_SIGNAL), kevent на него будет
сгенерирован даже если сигнал игнорируется.)

2. Если сигнал блокируется, то его обработчик будет вызван один раз
(независимо от того, сколько раз был послан сигнал) после снятия
блокировки.

3. Если сигнал обрабатывается по умолчанию как "отвергнуть сигнал"
(discard signal), то это полностью эквивалентно его игнорированию
(см. п. 1.1). В некоторых руководствах это действие явно именуется
"ignore". Действиями по умолчанию, в зависимости от типа сигнала,
могут также быть "завершить процесс" (возможно, с записью образа
памяти), "приостановить процесс" и "продолжить процесс".

4. Если процесс назначил сигналу собственный обработчик и сигнал
должен быть доставлен, то будет вызван этот обработчик.

Если у сигнала установлен через sigaction(2) флаг SA_RESETHAND,
то эмулируется поведение SysV signal(): обработчик сигнала будет
установлен равным SIG_DFL (обработка по умолчанию) в момент
доставки, т.е. непосредственно перед вызовом текущего
обработчика.

Hа время вызова обработчика текущий сигнал блокируется,
если не установлен флаг SA_NODEFER (то есть, сигнал добавляется
к маске, описанной в sa_mask). Это необходимо, чтобы
избежать зацикливания обработчика.

Обработчику передается номер текущего сигнала, что позволяет
использовать один обработчик для нескольких сигналов. Возможна
передача дополнительной информации (см. SA_SIGINFO в SUS).

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

Правило 2

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

Сигналы посылаются и доставляются асинхронно в подавляющем
большинстве случаев. Существует, по сути, лишь один случай
синхронной посылки сигнала: когда процесс посылает сигнал
сам себе, с помощью функций abort(3) или raise(3), или через
генерацию исключительной ситуации, вызывающей SIGSEGV,
SIGBUS, SIGIOT и аналоги. Согласно C99 и SUSv3, если в ответ
на raise(3) должен быть вызван обработчик сигнала, raise(3)
может вернуть управление только после того, как это сделает
обработчик. Кроме того, важным режимом является эмуляция
синхронной доставки размаскированием сигналов только в
отведенные для этого моменты времени (см. ниже).

В системах, совместимых с POSIX, вызов функции
raise(signo);
должен быть эквивалентен вызову конструкции:
kill(getpid(), signo);
Значит, в POSIX такую конструкцию можно рассматривать как
еще один способ синхронной посылки сигнала. Раздел SUSv3,
посвященный функции kill(), подробно обсуждает посылку
процессом сигнала самому себе и указывает, что в этом случае
сигнал должен быть доставлен до того, как kill() вернет
управление.

Правило 3

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

По-видимому, это весьма жесткое ограничение связано с
поддержкой архитектур, в которых обработчик асинхронного
сигнала не может напрямую обращаться к основной памяти
процесса. Распространённые реализации на распространённых
архитектурах (x86, amd64, Alpha, Sparc...) такого ограничения
не имеют, но мне неизвестно, оговорено ли это каким-либо
явным комплектом требований или стандартом.

Правило 4

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

1. Если для текущего сигнала не установлен флаг SA_RESTART, то
некоторые системные вызовы будут прерваны с ошибкой EINTR. Если
же флаг SA_RESTART установлен, то выполнение этих вызовов будет
продолжено.

Список прерываемых вызовов может быть приведен в sigaction(2);
это вызовы ввода-вывода и wait(2). SUSv3 такого списка не
приводит, однако говорит, что сигнал без SA_RESTART прерывает
любой вызов, который может возвращать ошибку EINTR. Детали
реализации (какой вызов прерывается) зависят от устройства
системы; типичные реализации могут прерывать вызовы
ввода-вывода на сокетах, терминалах, пайпах, но не на дисковых
устройствах (с возможным исключением в виде NFS и других
средств сетевого доступа к диску).

2. Функции семейства sleep (sleep(3), nanosleep(2) и т.п.) будут
прерваны любым доставленным сигналом, вне зависимости от наличия у
него флага SA_RESTART.

3. Вызов connect(2) в блокирующем режиме будет перван любым
доставленным сигналом, независимо от его флагов, однако сама операция
установки соединения будет продолжена в асинхронном режиме. Об
окончании операции можно узнать, передав дескриптор в poll(2) или
select(2): он будет помечен как готовый к записи.

4. Вызовы select(2), pselect(2) и poll(2) могут быть прерваны
сигналом.

Согласно SUSv3, poll(2) прерывается любым доставленным
сигналом; будут ли select(2) и pselect(2) учитывать флаг
SA_RESTART, определяет реализация.

5. Выполнение кода процесса и остальных системных вызовов будет
продолжено.

Следствия _для асинхронно доставляемых сигналов_

1. [Из п. 2] Из обработчика сигнала нельзя выполнять общий c другими
частями процесса нереентерабельный участок кода, если он не защищается
всякий раз путем блокировки соответствующих сигналов.

Здесь нереентерабельность понимается в широком смысле как
зависимость по статическим данным, требующим сериализации
доступа. Таким образом, нереентерабельной может быть как
отдельная функция, так и целая библиотека. Если несколько
участков кода обращаются к общим данным, требующим сериализации,
то все они будут взаимно нереентерабельны. В англоязычной
литературе есть более точный термин "async-signal-safe", то
есть, безопасный по отношению к асинхронным сигналам.

2. [Из п. 2, с. 1] Из обработчика сигнала нельзя вызывать
нереентерабельные библиотечные функции (н.б.ф.), если только
устройством программы не гарантируется, что на момент _каждого_
вызова _любой_ н.б.ф. все сигналы, чьи обработчики содержат вызовы
_любых_ н.б.ф., не будут заблокированы.

Так как внутренние зависимости между н.б.ф. полностью зависят
от реализации, вложенный вызов _любой_ н.б.ф. может привести
к неопределенному поведению _всех_ н.б.ф. К примеру,
изрядное количество библиотечных функций явно или неявно
вызывают malloc(3); так что разрушение структур malloc(3)
в результате вложенного вызова приведет к сбою многих б.ф.

Стандарт C99 утверждает, что из обработчика асинхронно
доставляемого сигнала можно вызывать только abort(3),
_exit(2), _Exit(), а также signal(3) с первым аргументом,
равным номеру текущего сигнала [C99 #7.14.1.1].
Стандарты POSIX и SUS приводят довольно объемистый список
реентерабельных функций. В прочих системах этот список,
очевидно, определяется реализацией.

3. [Из п. 1.4, п. 2] Выполнение обработчика сигнала может быть
прервано очередным доставленным сигналом. Чтобы избежать прерывания,
необходимо заблокировать все или некоторые сигналы на время работы
чувствительного участка в обработчике. Проще всего это делать,
указав маску sa_mask в параметре sigaction(2); эта маска будет
атомарно установлена на входе в обработчик, а на выходе из него
будет восстановлено предыдущее значение маски сигналов.

4. [Из с. 1, с. 3] Если один нереентерабельный обработчик установлен
для нескольких сигналов, то на время работы нереентерабельного участка
нужно блокировать все эти сигналы.

5. [Из п. 2, п. 3] Hеобходимо использовать модификатор volatile,
чтобы указать компилятору на асинхронность изменения переменной типа
sig_atomic_t.

6. [Из п. 3] Hе гарантируется, что обработчик сигнала может читать
статическую переменную, даже если она -- типа sig_atomic_t.

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

7. [Из п. 2, п. 3] Можно использовать только простое присваивание
переменным sig_atomic_t. В частности, над ними не следует использовать
операции ++ и --. Это касается как обработчиков сигналов, так и
основного потока (конечно, если соответствующие сигналы не заблокированы
на момент операций с переменной типа sig_atomic_t).

Атомарные арифметические и обменные операции над памятью существуют
во всех современных архитектурах (включая conditional store в
части RISC), но для них нет стандартных функций и компилятор
не обязан их использовать, например, из соображений оптимизации.

8. [Из п. 3] Если стандартная библиотечная функция, вызванная из
обработчика сигнала, вернула ошибку, то значение переменной errno
может быть не определено.

9. [Из п. 2] Вызов даже реентерабельной библиотечной функции из
обработчика сигнала может привести к изменению значения переменной
errno. Следовательно, если обработчик вызывает б.ф., то он должен
вначале сохранить значение errno, а перед возвратом восстановить его.

Правило 3 и следствие 8 исключают следствие 9. Проблема
здесь в том, что современные стандарты признают исторически
сложившуюся практику обращения к статическим переменным
вопреки правилу 3, но крайне не поощряют ее. Пока что это
приводит к подобным противоречиям.

10. [Из п. 2, п. 3, с. 1] "Трюк" с возвратом из обработчика сигнала
через longjmp(3), кочующий из книги в книгу (даже W.R.Stevens
приводит его), следует использовать с большой осторожностью.
Во-первых, longjmp(3) не восстановит статических переменных libc и
структуру кучи malloc(3) на момент вызова setjmp(3), а значит, он
ничем не поможет в решении проблемы реентерабельности. Во-вторых,
вызов longjmp(3) из обработчика обладает ограниченной переносимостью.

Изначально longjmp(3) из обработчика сигнала использовался,
чтобы обойти особенность 4.2BSD. Системные вызовы 4.2BSD
всегда продолжались после обработки сигнала, если обработчик
возвращал управление. Приходилось совершать longjmp(3),
чтобы прервать системный вызов.

Еще одно историческое применение longjmp(3) из обработчика
состояло в обходе изьяна pause(2). В системах без sigsuspend(2)
или sigpause(2) невозможно было гарантировать, что сигнал
не придет до вызова pause(2). Если сигнал посылался
однократно, как SIGALRM по истечению таймера, то приложение
могло "зависнуть". Для решения этой проблемы управление
из обработчика явно передавали через longjmp(3). W.R.Stevens
приводит пример использования longjmp(3) в обработчике
именно для этого случая.

Существует как минимум одна среда, претендующая на совместимость
с POSIX, в которой выход из обработчика сигнала через
longjmp(3) приводит к сбою приложения. Речь идет о Win32
и сигнале SIGINT. Этот сигнал посылается консольному
приложению при нажатии ^C и доставляется в специально
отведенную нить, даже если приложение спроектировано как
однонитевое. Конечно, этот прецедент может показаться
далеким от реалий Unix. Однако он иллюстрирует разнообразие
особенностей, с которыми можно столкнуться в POSIX-совместимых
системах.

11. [Из п. 2] Блокировка сигналов часто должна выполняться неразрывно
с другой операцией. Для этого существует ряд стандартных механизмов
и функций.

Согласно странице руководства sigaction(2) в системах на
основе BSD, несколько одновременно ожидающих доставки
сигналов будут доставлены так, что каждый последующий сигнал
прервет обработчик предыдущего перед его первой машинной
командой. Таким образом, избежать дальнейшего вложенного
вызова обработчиков можно, лишь атомарно установив маску
сигналов перед входом в текущий обработчик. Для этого служит
маска sa_mask, передаваемая как член структуры sigaction в
sigaction(2).

Чтобы приостановить выполнение программы до прихода
определенного сигнала (или любого из заданного множества
сигналов), существует системный вызов sigsuspend(2). Его
использование предполагает, что в остальное время интересующий
нас сигнал (или их множество) заблокирован, иначе можно его
упустить до вызова sigsuspend(2). Hо даже если sigprocmask(2)
вызвать непосредственно перед sigsuspend(2), все равно
образуется временное окно, на протяжении которого ожидаемый
сигнал может оказаться доставлен. Поэтому sigsuspend(2)
принимает в качестве аргумента маску сигналов, которую
атомарно устанавливает на время ожидания.

Системный вызов pselect(2) фактически совмещает в себе
функциональность select(2) и sigsuspend(2). Поэтому он
также принимает в качестве одного из аргументов маску
сигналов, которую атомарно устанавливает на время ожидания
событий.

12. [Из п. 2, с. 1] Для завершения процесса из обработчика сигнала
следует использовать _exit(2) (POSIX) или _Exit() (C99), которые
не имеют побочных эффектов, в отличие от exit(3).

Побочными эффектами exit(3) являются вызов зарегистрированных
с помощью atexit(3) деструкторов, закрытие потоков stdio,
удаление временных файлов и т.п. Все это наверняка повлечет
вызов н.б.ф.

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

13. [Из п. 4.1] Если хотя бы у одного сигнала, для которого установлен
обработчик, нет флага SA_RESTART и этот сигнал не заблокирован, то
по EINTR может быть прервана _любая_ стандартная библиотечная функция
ввода-вывода.

Практические соображения

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

Обращение из обработчика асинхронного сигнала к статическим
данным вопреки правилу 3 может считаться ограниченно
переносимым, так как работает в большинстве Unix-подобных
систем. Использовать его можно на свой страх и риск, однако
следует иметь ввиду возможные последствия для надежности и
переносимости приложения.

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

Если в вашем проекте сигналы большую часть времени разблокированы
и у некоторых из них не установлен флаг SA_RESTART, то может быть
удобно сократить до минимума число вызовов функций ввода-вывода.
Hужно быть готовым перезапустить каждый такой вызов, если он вернет
EINTR или выполнит операцию не полностью. При большом количестве
вызовов (например, при посимвольном вводе-выводе посредством stdio)
это потребует соответствующего числа практически повторяющихся
"оберток", что отрицательно скажется как на производительности, так
и на удобочитаемости исходных текстов.

Hаиболее простой и безопасный подход к обработке сигналов -- когда
обработчик устанавливает флаг типа sig_atomic_t, а основной поток
проверяет его и предпринимает необходимые действия. Если при этом
необходимо прерывать некоторые операции ввода-вывода, то следует или
блокировать сигналы на время остальных операций ввода-вывода, или
особо обрабатывать ошибку EINTR после _всех_ операций ввода-вывода.

В сложных случаях может оказаться удобнее эмулировать синхронные
сигналы. Для этого можно держать сигналы заблокированными большую
часть времени и разблокировать их только в специально отведенных,
реентерабельных точках программы. Особенно удобным для этой цели
является системный вызов pselect(2), который позволяет атомарно
устанавливать маску сигналов на время своего выполнения. Конечно,
это внесет задержку между отправкой сигнала и его обработкой.

В системах, где pselect(2) отсутствует, его можно частично
эмулировать, используя запись из обработчика сигнала в канал
(pipe). Для этого необходимо:

а) создать канал;
б) установить на обоих концах канала режим неблокирующего
ввода-вывода;
в) установить обработчик, который станет записывать в этот
канал 1 байт (любой, т.к. доставка через канал не будет
гарантированной) и устанавливать флаг в переменной
типа volatile sig_atomic_t;
г) включить читаемый дескриптор сигнального канала в
обработку poll(2)/select(2);
д) разблокировать сигнал;
е) вызвать poll(2)/select(2);
ж) заблокировать сигнал;
з) при наличии данных в сигнальном канале читать их оттуда
для очистки буфера;
и) если флаг установлен:
- сбросить флаг;
- предпринять необходимые действия;
к) вернуться к д).

Смысл записи в канал состоит в том, что poll(2)/select(2)
вернет управление сразу, если сигнал уже был доставлен в
обработчик. Иначе poll(2)/select(2) стал бы ждать других
событий, и реакция на сигнал произошла бы с задержкой.
Конечно, возможна потеря сигнала, если буфер сигнального
канала уже заполнен. Однако за счет установки и проверки
флага хотя бы один экземпляр сигнала будет когда-нибудь
замечен, а это вполне согласуется с моделью сигналов POSIX.

Так как сложные схемы на основе сигналов очевидно ограничены и плохо
переносимы, с сигналами всегда стоит придерживаться принципа K.I.S.S.:
"Keep it simple, stupid". Если вы выучили правила и видите, что
нетривиальное использование сигналов причиняет слишком много
неудобств, то вам пора рассмотреть другие средства IPC для вашего
проекта.

Заключение

Автор хотел бы искренне поблагодарить читателей эхи (телеконференции
FidoNet) RU.UNIX.PROG за ценные замечания и идеи для данной статьи.

Yar Tikhiy <yar at comp.chem.msu.su>

$yarId: signal.txt,v 1.48 2003/07/22 15:50:49 yar Exp $
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.02.2011, 15:00
Цитата Сообщение от niXman Посмотреть сообщение
нет.
так:
Если после async_wait поставить бесконечный цикл, то программа зациклится. Теперь пользователь, видя, что программа зациклилась, посылает ей сигнал с тем, чтобы прграмма сохранила данные и завершилась. В "моём" варианте так и произойдёт. В твоём - нет. Потому что обработчик сигналов запустится только в точке async_wait, но до ней исполнение не дойдёт (разве что ты будешь вызывать async_wait на каждой итерации цикла)
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 15:05
да нет же))) там единственное рекомендованное место для последующих вызовов async_wait() это хэндлер сигнала. Конечно можно позвать и из другого места, но это уже как бы подразумевает, что человек знает, что он делает и чем это может закончится.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.02.2011, 15:12
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
да нет же)))
ТОгда объясните мне, как мы попадём в обработчик сигнала изнутри бесконечного цикла, если попасть в обработчик можно только через async_wait?
1
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 15:30
на пальцах:
взвели обработчик
позвали 1й раз asinc_wait, который тут же вернулся
работаем, пусть в вечном цикле.

приходит сигнал ставим его в очередь и разрешаем сигналы
смотрим а был-ли asinc_wait()
если нет, то ничего не делаем, если был то выниманием самый старый сигнал из очереди и зовем заказанный на шаге 1 хэндлер.

хэндлер делает что надо и снова зовет asinc_wait()

по желанию, такой механизм можно реализовать в event driven стиле (в чистом виде kqueue() или велосипед на пайпах). Вариантов как сделать масса.

Все ухищрения на мой взгляд с 2мя целями:
1. Вывести пользовательский код из контекста сигналов (что позволит использовать любые функции в обработчике).
2. Дать стандартный механизм в стиле asio для работы с сигналами.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.02.2011, 15:39
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
приходит сигнал ставим его в очередь и разрешаем сигналы
В очередь, насколько я понимаю, ставит его "системная" часть boost'а. А кто разрешает сигналы? Просто такое объяснение "взвели", "позвали", "ставим" - оно плохое. Я, например, не понимаю, что из всего этого делает "мой" код, а что - "системный" код boost'а
1
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 15:50
Цитата Сообщение от Evg Посмотреть сообщение
В очередь, насколько я понимаю, ставит его "системная" часть boost'а. А кто разрешает сигналы? Просто такое объяснение "взвели", "позвали", "ставим" - оно плохое. Я, например, не понимаю, что из всего этого делает "мой" код, а что - "системный" код boost'а
Да, системная. Разрешает она же, метода для блокировки сигналов я там не вижу, т.е. получается если приложение захочет блокировать на время сигнал, то только удалить + добавить.

Ваш код делает только полезные вещи типа сброс дампа/переконфигурирование/etc + зовет async_wait()

Ну что вы от меня хотите, я это 2 часа назад 1й раз увидел по ссылке с этого форума, и глянул, а как оно работает на линуксе и фре.Причем о том, что без труда продираюсь через дебри их "богомерзких" шаблонов сказать не могу))) Вон niXman, говорил, что он в них как рыба в воде - его пытайте)))
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.02.2011, 16:37
g_u_e_s_t, я тебя не пытаю. В посту #43 ты сказал "да нет же". В посту #45 ты что-то объяснил, но я нифига не понял. Можешь ещё раз объяснить пост #45, нопонятным языком, и чтобы было понятно, что делает программист, а что - системная часть boost'а. Или написать полный вариант программы с asio, который бы реагировал на сигнал, полученный в бесконечном цикле, чтобы хоть понятно было, где и в чём я не прав, если уж не получается понятно словами объяснить
1
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 17:02
Ок пробую.
термены:
ос: система
вы/ваш/вами - программист/программа
boost - низкоуровневая "системная" реализация общаться с который можно только через публичные методы.
обработчик (сигнала) - низкоуровневый обработчик сигнала в boost.
хэндлер - ваш код вызываемый boost

вы: через конструктор или вызов add() устанавливаете хэндлер сигнала.
boost: создает очередь и устанавливает обработчик.
вы: зовете async_wait() (например из main()), управление тут же возвращается вам в не зависимости от того был получен сигнал или нет.

ос: посылает вашему процессу сигнал
обработчик: добавляет сигнал в очередь, разблокирует этот сигнал
boost: проверяет, что вы ждете этот сигнал (был вызван async_wait()), достает из очереди самый старый сигнал и запускает хэндлер
хэндлер: выполняет любую полезную работу использую любые доступные вам в boost api и сообщает boost о свой готовности принять следующий сигнал.

Во. Понятнее?

Пример кода: попробуйте зациклить пример из поста 39.
2
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.02.2011, 17:20
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Во. Понятнее?
Теперь понятнее. Т.е. принципиально нового в этой схеме ничего нет. И нет никаких отложенных обработок сигнала. Т.е. хэндлер будет запущен, грубо говоря, в момент получения сигнала, а не в тот момент, когда мы готовы его обрабатывать.

Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Пример кода: попробуйте зациклить пример из поста 39.
Был бы boost, я бы давно сам попробовал. Но у меня его нет и я никогда с ним не работал. Потому и просил более-менее рабочий пример, а не нарезки кода.

Теперь напишу, как я воспринимал boost'овский механизм. Судя по всему, воспринимал я его не правильно. Логика моего восприятия исходила из понятия "отложенной" обработки сигналов и перевода имени функции async_wait

ос: посылает вашему процессу сигнал
обработчик: добавляет сигнал в очередь, завершает работу, после чего прерванная сигналом программа продолжает работать
вы: зовёте async_wait, boost проверяет, что напихано в очередь и запускает хэндлеры. Псле завершения работы продолжаем исполнение. Таким образов вся обработка сигналов пройдёт в момент работы async_wait.

Добавлено через 1 минуту
Хотя из поста #49 мне непонятно, что принципиально лучшего даёт использование boost'а?
1
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 17:37
я писал предполагая, что вы знакомы с asio. Если вы занимаетесь разработкой на CPP то советую взглянуть. Например я не писал про io_service.run() думая что это и так понятно...
Если же вам ближе Си, то ближайшем аналогом идеологии asio будет цикл вокруг epoll_wait()/kevent()

Лучше/хуже я не возьмусь сравнивать. Лично мне не нравиться из-за не читабельности их шаблонов, но можно просто считать, что их не осилил)
2
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
25.02.2011, 18:11
разобрались

ко мне вопросы есть?

Добавлено через 26 секунд
g_u_e_s_t, ты все правильно объяснил.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.02.2011, 18:36
C asio вроди да, но я вот попутно между флудом тут, писал прототип на перле и столкнулся с одной не понятностью))) но наверное лучше отдельный топик создам если не разберусь.
1
0 / 0 / 0
Регистрация: 25.04.2011
Сообщений: 10
22.08.2011, 09:31
Доброго времени суток.

В процессе реализации программы возникла необходимость обработки сигналов. Суть в следующем:
Есть некий процесс. Ему посылается сигнал (пусть будет SIGTERM). Программа должна перехватить сигнал, и переключиться в другой режим работы, не завершаясь.

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

Code
1
2
3
4
5
6
7
8
9
10
11
12
struct sigaction sa;
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, SIGTERM);
sigprocmask(SIG_BLOCK, &newset, 0);
sa.sa_handler = term_handler;
sa.sa_mask = newset;
 
  while (1){
    sigaction(SIGTERM, &sa, 0);
    // некоторый код
  }
При таком раскладе сигнал блокируется полностью, в обработчик term_handler программа не заходит. Если убрать блокировку через sa_mask, то после завершения процедуры term_handler программа тут же завершает свою работу.

Собственно, вопрос: как мне заблокировать полученный сигнал после того, как я начал его обработку, чтобы программа продолжила свою работу?

P.S. Пишу на си под FreeBSD, если это имеет значение.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
22.08.2011, 10:08
Цитата Сообщение от olzan Посмотреть сообщение
Если убрать блокировку через sa_mask, то после завершения процедуры term_handler программа тут же завершает свою работу.
Это не нормально, покажите минимальный пример на котором это можно воспроизвести?
если я правильно понял, то как-то так?
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
sig_atomic_t got = 0;
 
void
handler(int sig)
{
        (void)sig;
 
        got = 1;
        (void)write(0, "\nsignal\n", 8);
}
 
void
mode_a(void)
{
        while (1) {
                printf("a");
                fflush(stdout);
                sleep(1);
                if (got)
                        break;
        }
        got = 0;
}
 
void
mode_b(void)
{
        while (1) {
                printf("b");
                fflush(stdout);
                sleep(1);
                if (got)
                        break;
        }
}
 
int
main()
{
        struct sigaction act;
 
        memset (&act, '\0', sizeof(act));
        act.sa_handler = handler;
        if (sigaction(SIGTERM, &act, NULL) == -1)
                err(1, "sigaction");
 
        printf("Started pid=%d\n", getpid());
 
        mode_a();
        mode_b();
 
        return (0);
}

Цитата Сообщение от olzan Посмотреть сообщение
Собственно, вопрос: как мне заблокировать полученный сигнал после того, как я начал его обработку, чтобы программа продолжила свою работу?
Он у вас и так блокирован в обработчике, если вы в реальном коде не ставите SA_NODEFER.
1
0 / 0 / 0
Регистрация: 25.04.2011
Сообщений: 10
24.08.2011, 09:09
g_u_e_s_t, спасибо за пример - помог разобраться в более корректном использовании обработчика сигнала. :)

Ошибка закралась в мой код, там идет работа с сокетом, и клиент отваливался из-за бага при проверке количества считанных из сокета байт. Сейчас исправил - все работает, спасибо за помощь. :)
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
24.08.2011, 09:18
Да не за что)
Но вообще на мой взгляд сама идея использовать сигнал для переключения логики программы, тем более SIG_TERM ущербна, например что будет если админ pid попутает. Я бы сделал управляющий сокет/пайп и переключался по команде оттуда.
0
0 / 0 / 0
Регистрация: 25.04.2011
Сообщений: 10
24.08.2011, 13:20
Постараюсь объяснить причины такого подхода..

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

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

P.S. Я и есть админ.)
P.P.S. SIG_TERM взят с потолка, как сигнал, который возможно перехватить и обработать.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
24.08.2011, 13:54
Цитата Сообщение от olzan Посмотреть сообщение
P.P.S. SIG_TERM взят с потолка, как сигнал, который возможно перехватить и обработать.
При таком раскладе все верно и SIG_TERM лучшый выбор, грамотно сдохнуть дело святое) Просто из вашего исходного поста было совершенно не понятно, что под "переключиться в другой режим работы" скрывается запуск процедуры завершения процесса.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
24.08.2011, 13:54
Помогаю со студенческими работами здесь

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

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

Задан вид периодического сигнала и его числовые характеристики. Для данного сигнала необходимо сделать
Задан вид периодического сигнала и его числовые характеристики. Для данного сигнала необходимо: 1) начертить осциллограмму; 2)...

Открыть файл формата WAV, воспроизвести его и отобразить график амплитуды и времени этого сигнала (файла), а также спектр сигнала
Здравствуйте ! Помогите пожалуйста с программой на Delphi 7. Не могу написать программу которая по нажатию вкладки ОТКРЫТЬ в меню...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
59
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru