Читаем Linux API. Исчерпывающее руководство полностью

В разделе 6.8 описаны функции setjmp() и longjmp(), позволяющие выполнять нелокальный переход из функции в код одной из процедур, вызвавших эту функцию. Мы можем это сделать и из обработчика. Это позволит восстановить работу программы после получения сигнала, сгенерированного аппаратным исключением (например, при ошибке доступа к памяти). Кроме того, этот метод позволяет перехватить сигнал и вернуть управление в конкретный участок программы. Например, оболочка по получении сигнала SIGINT (генерируемого, как правило, нажатием Ctrl+C) выполняет нелокальный переход для возвращения управления в основной цикл ввода (и, таким образом, чтения новой команды).

Однако при использовании стандартной функции longjmp() для выхода из обработчика сигнала возникает одна проблема. Ранее уже было отмечено, что после входа в обработчик ядро автоматически заносит активирующий его сигнал, так же как и любой другой указанный в поле act.sa_mask, в сигнальную маску процесса, а затем удаляет эти сигналы из маски, когда обработчик выполняет нормальный возврат.

Но что случается с сигнальной маской, когда мы выходим из обработчика с помощью функции longjmp()? Ответ зависит от происхождения конкретной реализации UNIX. В System V функция longjmp() не восстанавливает сигнальную маску, таким образом, блокированные сигналы так и остаются заблокированными до выхода из обработчика. Linux унаследовала модель поведения System V. (И, как правило, нам это мешает, ведь такое поведение оставляет сигнал, активировавший обработчик, заблокированным). В реализациях, восходящих к BSD, функция setjmp() сохраняет сигнальную маску в аргументе env, а функция longjmp() восстанавливает сохраненную маску. Иными словами, мы, возможно, не сможем использовать функцию longjmp() для выхода из обработчика сигнала.

В случае если при компиляции программы мы определяем макрос тестирования возможности _BSD_SOURCE, то функция setjmp() (glibc) следует семантике BSD.

Из-за вышеописанной разницы между двумя основными вариантами UNIX, комитет по подготовке стандарта POSIX.1-1990 решил не включать в него способ обработки сигнальной маски функциями setjump() и longjump(). Вместо этого комитет определил две новые функции — sigsetjump() и siglongjump(), предоставляющие явный контроль над сигнальной маской при выполнении нелокального перехода.

#include


int sigsetjmp(sigjmp_buf env, int savesigs);

Возвращает 0 при первом вызове, ненулевое значение при возврате через siglongjmp()

void siglongjmp(sigjmp_buf env, int val);

Функции sigsetjump() и siglongjump() работают аналогично функциям setjump() и longjump(). Единственное отличие заключается в типе аргумента env (sigjmp_buf вместо jmp_buf), а также в дополнительном аргументе savings функции sigsetjump(). Если значение savings не нуль, значит, сигнальная маска процесса, актуальная на момент вызова функции sigsetjump(), сохранена в переменной env и восстановлена последующим вызовом siglongjump() с указанным именем аргумента env. Если же значение аргумента savings равно 0, значит, сигнальная маска процесса не была ни сохранена, ни восстановлена.

Функции longjump() и siglongjump() не включены в перечень безопасных для асинхронных сигналов (см. табл. 21.1), так как вызов небезопасной для асинхронных сигналов функции после выполнения нелокального перехода несет в себе такие же риски, как и вызов этой функции из обработчика сигнала. Более того, если обработчик прерывает основную программу во время обновления структуры данных, после чего происходит выход из обработчика с помощью нелокального перехода, это может оставить структуру в недозаполненном состоянии. Применение функции sigprocmask(), временно блокирующей сигнал во время выполнения важных обновлений, — один из способов избежать проблем в такой ситуации.


Пример программы

В листинге 21.2 демонстрируется различие в методах обработки сигнальной маски для нелокальных переходов двух типов. Эта программа устанавливает обработчик для сигнала SIGINT. Она создана таким образом, чтобы разрешать использование сочетания функций setjmp() плюс longjmp() или sigsetjmp() плюс siglongjmp() для выхода из обработчика сигнала в зависимости от того, был ли определен макрос компиляции USE_SIGSETJMP. Программа отображает текущие установки сигнальной маски как на момент входа в обработчик сигнала, так и после выполнения нелокального перехода, переносящего управление из обработчика сигнала обратно в основную программу.

При создании программы с тем расчетом, что для выхода из обработчика сигнала применяется функция longjump(), на экране мы увидим примерно следующее:

$ make — s sigmask_longjmp Компиляция по умолчанию с использованием setjmp()

$ ./sigmask_longjmp

Signal mask at startup:

Calling setjmp()

Нажмите Ctrl-C для генерации SIGINT

Received signal 2 (Interrupt), signal mask is:

2 (Interrupt)

After jump from handler, signal mask is:

2 (Interrupt)

Перейти на страницу:

Похожие книги

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных
1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных