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

Функция atexit() добавляет аргумент func в список функций, которые вызываются при завершении процесса. В определении функции func не должно быть аргументов и возвращаемого значения, то есть она должна иметь примерно такой вид:

void

func(void)

{

/* Выполняем какие-то действия */

}

Стоит отметить, что при возникновении ошибки функция atexit() возвращает ненулевое значение (не обязательно –1).

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

Внутри обработчика выхода можно выполнить практически любое действие на ваш выбор, включая регистрацию дополнительных обработчиков, которые помещаются в начало списка еще не вызванных обработчиков. Однако если один из обработчиков выхода не сможет вернуть управление (либо из-за вызова _exit(), либо в результате завершения процесса с помощью сигнала — например, когда обработчик сделал вызов raise()), остальные обработчики не будут вызваны. Кроме того, будут проигнорированы действия, которые обычно выполняются вызовом exit() (то есть сброс буферов stdio).

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

SUSv3 требует, чтобы процесс мог зарегистрировать как минимум 32 обработчика выхода. Максимально возможное количество обработчиков, доступных для регистрации в данной реализации, можно узнать с помощью вызова sysconf(_SC_ATEXIT_MAX) (однако не существует способа узнать, сколько обработчиков уже было зарегистрировано). Библиотека glibc может почти полностью снять это ограничение, если поместить обработчики выхода в динамически выделяемый связанной список. В системе Linux вызов sysconf(_SC_ATEXIT_MAX) возвращает 2147483647 (то есть максимальное целое 32-битное число со знаком). Иными словами, прежде, чем будет достигнуто это ограничение, мы исчерпаем какой-то другой ресурс (например, память).

Дочерний процесс, созданный с помощью вызова fork(), наследует копию списка зарегистрированных обработчиков выхода своего родителя. Когда процесс выполняет функцию exec(), все обработчики удаляются (это необходимо, потому что функция exec() заменяет код обработчиков выхода вместе с остальным программным кодом).

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

У обработчиков выхода, зарегистрированных с помощью вызова atexit(), есть два ограничения. Во-первых, вызывающийся обработчик выхода не знает, какой код был передан в функцию exit(). Иногда осведомленность об этом коде может оказаться полезной; например, можно выполнять разные действия в зависимости от того, завершается ли процесс удачно или неудачно. Второе ограничение заключается в том, что мы не можем указать аргумент для вызываемого обработчика выхода. Это могло бы пригодиться для изменения поведения обработчика или для многократной регистрации одной и той же функции, но с разными аргументами.

Для обхода этих ограничений библиотека glibc предоставляет альтернативный (нестандартный) способ регистрации обработчиков выхода: вызов on_exit().

#define _BSD_SOURCE /* Или: #define _SVID_SOURCE */

#include


int on_exit(void (*func)(int, void *), void *arg);


Возвращает 0 при успешном завершении или ненулевое значение при ошибке

Аргумент func вызова on_exit() является указателем на функцию следующего вида:

void

func(int status, void *arg)

{

/* Выполняем освобождение ресурсов */

}

При вызове функции func() передаются два аргумента: status, который был передан при вызове exit(), и копия аргумента arg, который был указан во время регистрации функции. И хотя arg объявлен в качестве указателя, он открыт для различных интерпретаций со стороны программиста. Он может указывать на некую структуру данных, но с тем же успехом его можно применять в качестве целого числа или другого скалярного значения, если аккуратно выполнить приведение типов.

Как и atexit(), вызов on_exit() в случае ошибки возвращает ненулевое значение (не обязательно –1).

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

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

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#.Введите сюда краткую аннотацию

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

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