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

Существует одно обстоятельство, при котором вызов exit() и возвращение из функции main() не являются эквивалентными. Если во время завершения предпринимаются какие-либо действия с использованием локальных переменных функции main(), то возвращаемое значение этой функции будет неопределенным. Так, например, случается, когда локальная переменная функции main() указывается в вызовах setvbuf() или setbuf() (см. раздел 13.2).

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

В стандарте C89 поведение при таких обстоятельствах не определено; программа может завершиться с произвольным статусом. Так, например, происходит на платформе Linux в сочетании с компилятором gcc: код завершения программы берется из какого-то случайного значения в стеке или определенном регистре ЦПУ. Следует избегать завершения программ таким образом.

Стандарт C99 требует, чтобы окончание главной функции было эквивалентно вызову exit(0). Для того чтобы программа в системе Linux вела себя именно так, нужно скомпилировать ее с использованием параметра gcc — std=c99.


25.2. Завершение процесса в подробностях


Во время нормального и аварийного завершения процесса выполняются следующие действия.

• Закрываются дескрипторы открытых файлов, потоки каталогов (см. раздел 18.8), дескрипторы каталога сообщений (см. справочные страницы вызовов catopen(3) и catgets(3)) и дескрипторы преобразования (см. справочную страницу вызова iconv_open(3)).

• В результате закрытия дескрипторов снимаются все блокировки файлов, которые удерживал данный процесс (см. главу 51).

• Если это контролирующий процесс в контролирующем терминале, каждому из процессов в активной группе терминала посылается сигнал SIGHUP, а сам терминал отключается от сессии. Данный этап будет рассмотрен подробнее в разделе 34.6.

• Закрываются любые именованные семафоры POSIX, открытые в вызывающем процессе, как будто при вызове sem_close().

• Закрываются любые очереди сообщений POSIX, открытые в вызывающем процессе, как будто при вызове mq_close().

• Если в результате завершения процесса его группа становится «осиротевшей», то всем остановленным процессам, которые в ней все еще находятся, по очереди высылаются сигналы SIGHUP и SIGCONT. Данный этап будет рассмотрен подробнее в подразделе 34.7.4.

• Снимаются любые блокировки памяти, установленные с помощью вызовов mlock() или mlockall() (см. раздел 46.2).

• Сбрасываются любые отображения в память, созданные с помощью вызова mmap().


25.3. Обработчики выхода


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

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

Факт того, что обработчики выхода не вызываются, если процесс завершается посредством сигнала, в некоторой степени ограничивает их применение. Лучшее, что мы можем сделать, — предусмотреть обработчики для сигналов, которые могут быть посланы процессу, и заставить их устанавливать флаг, который приводит к вызову exit() главной программой. (Поскольку exit() не является одной из безопасной для асинхронных сигналов функций, перечисленных в табл. 21.1, ее, как правило, нельзя вызывать из обработчика сигнала.) Но даже в этом случае обработчик не сможет среагировать на сигнал SIGKILL, для которого нельзя изменить действие по умолчанию. Это одна из причин, по которой мы должны избегать применения этого сигнала для завершения процессов (как отмечено в разделе 20.2); вместо него следует использовать сигнал SIGTERM, который передается по умолчанию командой kill.


Регистрация обработчиков выхода

В GNU библиотеке C предусмотрено два способа регистрации обработчиков выхода. Первый из них описан в стандарте SUSv3 и заключается в использовании функции atexit().

#include


int atexit(void (*func)(void));

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

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

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

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

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

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