|
0 / 0 / 0
Регистрация: 24.10.2009
Сообщений: 16
|
|
Перехват Сигнала28.05.2010, 11:03. Показов 18417. Ответов 58
Метки нет (Все метки)
Тема работы "Сигналы". Мне дали доп задание: "Один источник посылает сигнал(любой, любым способом). Есть приёмник, который должен принимать эти сигналы. Нужно добавить перехватчик сигналов, и вывести количество перехваченных сигналов, если это получится". Кода нет вообще. Киньте хоть ссылки, где прочитать про эти перехватчики можно, ато я что-то совсем ничего не могу найти.
0
|
|
| 28.05.2010, 11:03 | |
|
Ответы с готовыми решениями:
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
|
|
|
|
||
| 25.02.2011, 15:00 | ||
|
0
|
||
|
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
|
|
| 25.02.2011, 15:05 | |
|
да нет же))) там единственное рекомендованное место для последующих вызовов 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
|
|
|
|
||
| 25.02.2011, 15:39 | ||
|
1
|
||
|
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
|
||
| 25.02.2011, 15:50 | ||
|
Ваш код делает только полезные вещи типа сброс дампа/переконфигурирование/etc + зовет async_wait() Ну что вы от меня хотите, я это 2 часа назад 1й раз увидел по ссылке с этого форума, и глянул, а как оно работает на линуксе и фре.Причем о том, что без труда продираюсь через дебри их "богомерзких" шаблонов сказать не могу))) Вон niXman, говорил, что он в них как рыба в воде - его пытайте)))
1
|
||
|
|
|
| 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
|
|
|
|
|||
| 25.02.2011, 17:20 | |||
|
Теперь напишу, как я воспринимал 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
|
|
|
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, чтобы вызвать процедуру для ветвления логики программы, а потом заблокировать сам сигнал. И вот тут начинаются проблемы... Пробовал примерно такой код:
Собственно, вопрос: как мне заблокировать полученный сигнал после того, как я начал его обработку, чтобы программа продолжила свою работу? P.S. Пишу на си под FreeBSD, если это имеет значение.
0
|
||||||
|
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
|
||||||||
| 22.08.2011, 10:08 | ||||||||
|
если я правильно понял, то как-то так?
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 | ||
|
0
|
||
| 24.08.2011, 13:54 | |
|
Помогаю со студенческими работами здесь
59
Извлечение сигнала заданной частоты из более сложного сигнала Моделирование сигнала, шумового процесса, смеси сигнала с шумом
Открыть файл формата WAV, воспроизвести его и отобразить график амплитуды и времени этого сигнала (файла), а также спектр сигнала Два коротких сигнала при запуске, пауза и снова два коротких сигнала Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
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-среде способ разработки чаще всего предполагает
монорепозиторий в котором находятся все исходники.
При создании нового решения, мы просто добавляем нужные проекты
и имеем. . .
|