Часть 2. Дополнительные сведения о сигналах
Серия контента:
Этот контент является частью # из серии # статей: Работа с сигналами в Linux
Этот контент является частью серии: Работа с сигналами в Linux
Следите за выходом новых статей этой серии.
Сигналы реального времени
В сигналах, стандартизированных в POSIX, существуют свои, отчасти досадные, ограничения. Например, нельзя быть уверенным в том, что множество сигналов, посланных поочередно, не будут слиты вместе.
Для обхода этого и других ограничений были созданы сигналы реального времени. Системы, которые поддерживают сигналы реального времени, поддерживают и стандартный механизм сигналов POSIX. Следует учитывать, что для достижения максимальной переносимости желательно применять POSIX-реализацию сигналов, используя сигналы реального времени лишь там, где возникает необходимость в их особых свойствах.
Отличия сигналов реального времени от обычных сигналов
Как уже было сказано, сигналы реального времени обеспечивают доставку множества одинаковых, отосланных поочередно сигналов – эти сигналы не будут сливаться.
Кроме того, сигналы реального времени дают гарантию упорядоченной доставки сигналов – если вы поочередно послали несколько сигналов реального времени, то можете быть уверены в том, что они в полном порядке дойдут до адресата и будут упорядочены – сигналы с меньшим номером придут первыми, перед сигналами с большими номерами.
Естественно, порядок доставки сигналов и правила доставки множества отосланных поочередно сигналов не определены для сигналов, не относящихся к расширению реального времени.
Упорядочивание и постановка в очередь сигналов реального времени
Точные номера сигналов реального времени не специфицированы, но можно быть уверенным в том, что все сигналы с номерами между SIGRTMIN и SIGRTMAX являются сигналами реального времени.
Для работы с сигналами реального времени применяются те же самые системные вызовы, что и для работы с обычными сигналами (эти системные вызовы были рассмотрены в предыдущей статье).
В качестве примера напишем небольшую программу, производящую отсылку набора традиционных сигналов и набора сигналов реального времени, для иллюстрации упорядочивания и постановки в очередь сигналов реального времени:
Программа компилируется командой:
и выполняет следующие функции: вначале блокируются сигналы, предлагающиеся к отправке, для того чтобы избежать их немедленной доставки; затем, после отправки этих сигналов, сигналы разблокируются, что вызывает их немедленную и одновременную доставку. Затем список сигналов выводится на экран в порядке их поступления.
Результат работы программы
полностью подтверждает все, что было сказано выше о сигналах – одинаковые сигналы из стандарта POSIX, отосланные друг за другом, сливаются в один сигнал (SIGUSR1), а сигналы реального времени доходят все, без потерь, причем сигналы с меньшими номерами доставляются перед сигналами с большими номерами (упорядочиваются).
Получение контекста сигнала
В сигналах, обсуждавшихся в этой и предыдущей статьях, не передавалось никакой дополнительной информации – приложению был доступен только факт приема сигнала, и ничего более. Тем не менее было бы весьма неплохо иметь возможность узнать, что явилось причиной высылки сигнала – узнать контекст сигнала.
Контекст сигнала можно получить, используя специальный обработчик сигнала, который определяется следующим образом:
где указатель на siginfo_t предоставляет доступ к контексту сигнала, а указатель void * context используется некоторыми системными библиотеками, рассмотрение которых выходит за рамки данной статьи.
Поскольку определение обработчика сигнала изменилось, мы не можем использовать старый член структуры sigaction – sa_handler для передачи системному вызову указателя на обработчик. Для этого следует использовать новый, не рассмотренный ранее член структуры – sa_sigaction. Стоит помнить, что и sa_handler, и sa_sigaction используют одну и ту же память (реализовано через union), поэтому нельзя использовать одновременно два способа передачи указателя на обработчик сигнала системному вызову.
Кроме того, программа должна указать ядру на необходимость передачи в обработчик сигнала полной информации о контексте сигнала. Производится это путем установки флага SA_SIGINFO для члена sa_mask структуры sa_sigaction.
Структура siginfo_t содержит информацию о том, где и почему был сгенерирован сигнал. Эта структура содержит два обязательных члена: sa_signo и si_code и ряд необязательных членов, зависящих от конкретного сигнала. sa_signo содержит номер доставленного сигнала и всегда равен значению параметра signum обработчика сигнала. Второй член – si_code – содержит код причины генерации сигнала. Для большинства сигналов si_code принимает следующие значения.
- SI_KERNEL – сигнал сгенерирован ядром.
- SI_QUEUE – пользовательское приложение вызвало системный вызов sigqueue() для отправки сигнала.
- SI_TKILL – пользовательское приложение использовало системный вызов tkill().
- SI_USER – пользовательское приложение вызвало системный вызов kill() для отправки сигнала.
Несколько сигналов, посылаемых ядром (а именно SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGCHLD), имеют свои значения si_code вместо стандартных. Часть из возможных значений si_code для каждого из этих сигналов перечислена ниже.
ILL_ILLOPC – неправильный код операции, привилегированный код операции, ошибка сопроцессора.
FPE_INTDIV – деление целого на ноль.
FPE_FLTDIV – деление числа с плавающей точкой на ноль.
FPE_INTOVF – переполнение целого.
FPE_FLTOVF – переполнение числа с плавающей точкой.
SEGV_MAPERR – адрес не отображается на объект.
SEGV_ACCERR – неверные права доступа для адреса.
BUS_ADRALN – неверное выравнивание адреса.
BUS_ADRERR – несуществующий физический адрес.
BUS_OBJERR – специфичный для объекта сбой оборудования.
CLD_EXITED – дочерний процесс завершен.
CLD_KILLED – дочерний процесс уничтожен.
CLD_STOPPED – дочерний процесс приостановлен.
Для иллюстрации принципов получения контекста сигнала напишем небольшую программу, вызывающую нарушение сегментации при помощи прямого обращения по адресу к чужой области памяти, и печатающую контекст сигнала SIGSEGV.
Отправка данных с сигналом
Механизм, использующий siginfo_t, также позволяет присоединять к сигналам какие-нибудь данные. Это может быть указатель или целочисленное значение. Элемент отправляемых данных объявлен так:
Соответственно, в любой момент времени мы можем отослать либо целочисленное значение, либо указатель, но никак не оба типа данных сразу.
Чтобы привязать к сигналу данные при помощи union sigval, нужно для генерации сигнала использовать функцию sigqueue(), имеющую следующий прототип:
где pid должен быть корректным идентификатором процесса, отрицательные значения не допускаются. signal – номер посылаемого сигнала; он может быть равен нулю – тогда sigqueue() проверит возможность посылки сигнала процессу-получателю. Последний параметр – value – представляет собой данные, посылаемые с сигналом.
Чтобы принять данные, посланные вместе с сигналом, приложение должно быть готовым к работе с контекстом сигнала, а именно: использовать специальный обработчик сигнала и использовать SA_SIGINFO при регистрации обработчика.
Если член si_code структуры siginfo_t равен SI_QUEUE, то, значит, вместе с сигналом нам пришли некие данные. В этом случае структура siginfo_t предоставляет член si_value, в котором содержится значение, переданное вместе с сигналом. В целом же программа, принимающая данные вместе с сигналом, не особо отличается от той, которая была приведена в предыдущей главе.
Механизм сигналов, включающий в себя и сигналы стандарта POSIX, и Real-Time сигналы, представляет собой довольно мощное средство для межпроцессного взаимодействия. В Unix-like-системах сигналы довольно часто используются для того, чтобы сообщить приложению о некоем событии, способном повлиять на работоспособность приложения. Впрочем, рассмотрение остальных аспектов применения сигналов выходит за рамки данного цикла, и для их изучения стоит обратиться к специальной литературе.
5.7. Сигналы реального времени Posix
5.7. Сигналы реального времени Posix
За прошедшие годы сигналы в Unix много раз претерпевали революционные изменения.
1. Модель сигналов, предлагавшаяся в Unix Version 7 (1978), была ненадежной. Сигналы могли быть потеряны, и процессу было трудно отключить отдельные сигналы при выполнении отдельных участков кода.
2. В версии 4.3BSD (1986) надежные сигналы были добавлены.
3. Версия System V Release 3.0 (1986) также добавила надежные сигналы, хотя и иначе, чем BSD.
4. Стандарт Posix.1 (1990) увековечил модель надежных сигналов BSD, и эта модель подробно описана в главе 10 [21].
5. Posix.1 (1996) добавил к модели Posix сигналы реального времени. Это произросло из расширений реального времени Posix.1b (которые были названы Posix.4).
Почти все системы Unix в настоящее время поддерживают надежные сигналы, а новейшие системы предоставляют также и сигналы реального времени стандарта Posix. (Следует различать надежные сигналы и сигналы реального времени.) О сигналах реального времени следует поговорить подробнее, поскольку мы уже столкнулись с некоторыми структурами, определяемыми этим расширением стандарта, в предыдущем разделе (структуры sigval и sigevent).
Сигналы могут быть отнесены к двум группам:
1. Сигналы реального времени, которые могут принимать значения между SIGRTMIN и SIGRTMAX включительно. Posix требует, чтобы предоставлялось по крайней мере RTSIG_MAX сигналов, и минимальное значение этой константы равно 8.
2. Все прочие сигналы: SIGALRM, SIGINT, SIGKILL и пр.
ПРИМЕЧАНИЕ
В Solaris 2.6 обычные сигналы Unix нумеруются с 1 по 37, а 8 сигналов реального времени имеют номера с 38 по 45. В Digital Unix 4.0B обычные сигналы нумеруются с 1 по 32, а 16 сигналов реального времени имеют номера с 33 по 48. Обе реализации определяют SIGRTMIN и SIGRTMAX как макросы, вызывающие sysconf, что позволяет изменять их значения.
Далее все зависит от того, установлен ли процессом, получившим сигнал, флаг SA_SIGINFO при вызове sigaction. В итоге получаются четыре возможных сценария, приведенных в табл. 5.2.
Таблица 5.2. Поведение сигналов Posix в реальном времени в зависимости от SA_SIGINFO
Сигнал | Флаг SA_SIGINFO указан | Флаг SA_SIGINFO не указан |
---|---|---|
От SIGRTMIN до SIGRTMAX | Гарантируются характеристики реального времени | Характеристики реального времени не обязательны |
Все прочие сигналы | Характеристики реального времени не обязательны | Характеристики реального времени не обязательны |
Смысл фразы «характеристики реального времени не обязательны» следующий: некоторые реализации могут обрабатывать эти сигналы как сигналы реального времени, но это не обязательно. Если мы хотим, чтобы сигналы обрабатывались как сигналы реального времени, мы должны использовать сигналы с номерами от SIGRTMIN до SIGRTMAX и должны указать флаг SA_SIGINFO при вызове sigaction при установке обработчика сигнала.
Термин «характеристики реального времени» подразумевает следующее:
? Сигналы помещаются в очередь. Если сигнал будет порожден трижды, он будет трижды получен адресатом. Более того, повторения одного и того же сигнала доставляются в порядке очереди (FIFO). Мы вскоре покажем пример очереди сигналов. Если же сигналы в очередь не помещаются, трижды порожденный сигнал будет получен лишь один раз.
? Когда в очередь помещается множество неблокируемых сигналов в диапазоне SIGRTMIN—SIGRTMAX, сигналы с меньшими номерами доставляются раньше сигналов с большими номерами. То есть сигнал с номером SIGRTMIN имеет «больший приоритет», чем сигнал с номером SIGRTMIN+1, и т.д.
? При отправке сигнала, не обрабатываемого как сигнал реального времени, единственным аргументом обработчика является номер сигнала. Сигналы реального времени несут больше информации, чем прочие сигналы. Обработчик для сигнала реального времени, устанавливаемый с флагом SA_SIGINFO, объявляется как
void func(int signo, siginfo_t *info, void *context);
где signo— номер сигнала, a siginfo_t — структура, определяемая как
int si_signo; /* то же, что и signo */
union sigval si_value; /* целое или указатель от отправителя */
На что указывает context — зависит от реализации.
ПРИМЕЧАНИЕ
Обработчик сигналов, не являющихся сигналами реального времени, вызывается с единственным аргументом. Во многих системах существует старое соглашение о вызове обработчиков сигналов с тремя аргументами, которое предшествовало стандарту реального времени Posix.
Тип siginfo_t является единственной структурой Posix, определяемой оператором typedef с именем, оканчивающимся на _t. В листинге 5.14 мы объявляем указатели на эти структуры как siginfo_t * без слова struct.
? Для работы с сигналами реального времени добавлено несколько новых функций. Например, для отправки сигнала какому-либо процессу используется функция sigqueue вместо kill. Новая функция позволяет отправить вместе с сигналом структуру sigval.
Сигналы реального времени порождаются нижеследующими функциями Posix.1, определяемыми значением si_code, которое хранится в структуре siginfo_t, передаваемой обработчику сигнала.
? SI_ASYNCIO — сигнал был порожден по завершении асинхронного запроса на ввод или вывод одной из функций Posix aio_XXX, которые мы не рассматриваем;
? SI_MESGQ — сигнал был порожден при помещении сообщения в пустую очередь сообщений (как в разделе 5.6);
? SI_QUEUE — сигнал был отправлен функцией sigqueue. Пример будет вскоре приведен;
? SI_TIMER — сигнал был порожден по истечении установленного функцией timer_settime времени. Эту функцию мы не описываем;
? SI_USER — сигнал был отправлен функцией kill.
Если сигнал был порожден каким-либо другим событием, si_code будет иметь значение, отличающееся от приведенных выше. Значение поля si_value структуры siginfo_t актуально только в том случае, если si_code имеет одно из следующих значений: SI_ASYNCIO, SI_MESGQ, SI_QUEUE и SI_TIMER.
Данный текст является ознакомительным фрагментом.
Читать книгу целиком
Похожие главы из других книг:
10.6. Сигналы POSIX
10.6. Сигналы POSIX API POSIX основан на API sigvec() из BSD 4.2 и 4.3. С небольшими изменениями этот API можно было отнести к возможностям API как V7, так и System V Release 3. POSIX сделал эти изменения и переименовал API sigaction(). Поскольку интерфейс sigvec() широко не использовался, мы не будем его описывать.
Режим реального времени
Режим реального времени Операционная система Linux обеспечивает две стратегии планирования в режиме реального времени (real-lime): SCHED_FIFO и SCHED_RR. Стратегия планирования SCHED_OTHER является обычной стратегией планирования, т.е. стратегий планирования не в режиме реального времени.
Часы реального времени
Часы реального времени Часы реального времени (real-time clock, RTC) представляют собой энергонезависимое устройство для сохранения системного времени. Устройство RTC продолжает отслеживать время, даже когда система отключена, благодаря небольшой батарее, которая обычно
Опрос и установка часов реального времени, и кое-что еще
Опрос и установка часов реального времени, и кое-что еще Независимо от применения таймеров, вы можете также опрашивать и устанавливать часы реального времени, а также и плавно подстраивать их. Для этих целей можно использовать следующие
1.2. Особенности отладки в системах реального времени
1.2. Особенности отладки в системах реального времени Отладка в СРВ направлена на обнаружение и исправление ошибок в прикладном коде. Она является одним из этапов кросс-разработки, схему которой можно представить следующим образом. Разработка приложения ведется как
1.3. Ошибки в системах реального времени
1.3. Ошибки в системах реального времени Отмеченные выше методы отладки позволяют выявлять и устранять ошибки следующего характера:1. Ошибки в программном обеспечении, влекущие непнеправильное выполнение задачи (безотносительно времени). Обычные ошибки, обнаруживаемые
За пределы POSIX: сигналы в сети
За пределы POSIX: сигналы в сети А теперь, «на закуску», посмотрим справочную информацию по системной команде kill (послать сигнал). Вы, должно быть, помните, что в QNX есть дополнительная возможность получить справку по любой команде системы, используя команду # use
12.6. Сигналы реального времени
12.6. Сигналы реального времени Учитывая некоторые ограничения модели сигналов POSIX, например, недостающую возможность присоединения к сигналам никаких данных и вероятность того, что множество сигналов сольются в одной доставке, было разработано расширение POSIX Real Time Signals
8.1.6 Работа в режиме реального времени
8.1.6 Работа в режиме реального времени Режим реального времени подразумевает возможность обеспечения достаточной скорости реакции на внешние прерывания и выполнения отдельных процессов в темпе, соизмеримом с частотой возникновения вызывающих прерывания событий.
Изменения методологии в режиме реального времени
Изменения методологии в режиме реального времени И, наконец, последний из наиболее важных факторов при создании методологии — подгонка нужной методологии непосредственно в ходе работ. Коль скоро мы понимаем, что каждый проект заслуживает своей собственной методологии,
Сигналы Posix: функции типа Async-Signal-Safe
Сигналы Posix: функции типа Async-Signal-Safe Недостаток пpoгрaммы из листинга 5.8 в том, что она вызывает mq_notify, mq_receive и printf из обработчика сигнала. Ни одну из этих функций вызывать оттуда не следует.Функции, которые могут быть вызваны из обработчика сигнала, относятся к группе,
1.6.13. Правило экономии: время программиста стоит дорого; поэтому экономия его времени более приоритетна по сравнению с экономией машинного времени
1.6.13. Правило экономии: время программиста стоит дорого; поэтому экономия его времени более приоритетна по сравнению с экономией машинного времени «В ранние мини-компьютерные времена Unix» вынесенная в заголовок идея была довольно радикальной (машины тогда работали
Василий Щепетнёв: Сигналы неточного времени Василий Щепетнев
Василий Щепетнёв: Сигналы неточного времени Василий Щепетнев Опубликовано 18 октября 2011 года Порой встречается выражение «врождённая грамотность». Так называют способность писать без ошибок у человека, который правила то ли забыл, то ли никогда и
«Яндекс» научили искать в режиме реального времени Андрей Письменный
«Яндекс» научили искать в режиме реального времени Андрей Письменный Опубликовано 14 июля 2010 года Поисковик «Яндекс» начал использование системы поиска, которая позволяет искать по только что созданным документам — буквально через минуты после их