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

Чтобы разобраться, что такое реентерабельные функции, сначала рассмотрим различие между однопоточными и многопоточными программами. Классические программы UNIX имеют только один поток выполнения: ЦПУ обрабатывает инструкции одного логического потока выполнения программы. В многопоточной программе присутствуют несколько независимых и параллельных (concurrent) логических потоков в рамках одного процесса.

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

Функция называется реентерабельной в том случае, если она может одновременно безопасно выполняться несколькими потоками в рамках одного процесса. В данном контексте слово «безопасно» означает, что функция достигает ожидаемого результата вне зависимости от текущего состояния любого другого потока выполнения.

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

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

Такие случаи на самом деле далеко не редкость при работе со стандартной библиотекой С. Например, в подразделе 7.1.3 мы уже отмечали, что функции malloc() и free() работают со связанными списками освобожденной памяти, доступной для перераспределения из динамической области. Если вызов функции malloc(), осуществленный основной программой, прерывается обработчиком сигнала, который также вызывает функцию malloc(), то такой связанный список может быть поврежден. По этой причине семейство функций malloc() и другие библиотечные функции, которые применяют их, являются нереентерабельными.

Другие библиотечные функции являются нереентерабельными, потому что они возвращают информацию, используя статически выделенную память. Примерами таких функций (описываются по тексту книги) могут быть crypt(), getpwnam(), gethostbyname() и getservbyname(). Если обработчик сигнала вызывает одну из этих функций, то он перезапишет информацию, возвращенную любым предыдущим вызовом той же функции из основной программы (или наоборот).

Функции могут быть нереентерабельными, если они используют для внутренних операций статические структуры данных. Самыми очевидными примерами могут быть члены библиотеки stdio: printf(), scanf() и т. д, обновляющие внутренние структуры данных для буферизированного ввода-вывода. Таким образом, задействуя в обработчике сигнала функцию printf(), мы иногда можем увидеть странный вывод или даже аварийное завершение программы, или повреждение данных, если обработчик события прерывает программу во время выполнения функции printf() или другой функции из библиотеки stdio.

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

Если функция является нереентерабельной, то страница справочника будет, как правило, содержать явное или неявное указание на это. В частности, обращайте внимание на утверждения, что функция задействует или возвращает данные в статически выделенных переменных.


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

В листинге 21.1 продемонстрирована нереентерабельная природа функции crypt() (см. раздел 8.5). В качестве аргументов командной строки данная программа принимает две строки текста. Программа выполняет следующие шаги.

1. Вызов функции crypt() для зашифровки первой строки текста — аргумента и копирование этой строки текста в отдельный буфер с помощью функции strdup().

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

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

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

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

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