11.19. Функции gethostbyname_r и gethostbyaddr_r
11.19. Функции gethostbyname_r и gethostbyaddr_r
Чтобы превратить функцию, не допускающую повторное вхождение, такую как gethostbyname, в повторно входимую, можно воспользоваться двумя способами.
1. Вместо заполнения и возвращения статической структуры вызывающий процесс размещает структуру в памяти, и функция, допускающая повторное вхождение, заполняет эту структуру. Эта технология используется для перехода от функции gethostbyname (которая не допускает повторное вхождение) к функции gethostbyname_r (которая допускает повторное вхождение). Но это решение усложняется, поскольку помимо того, что вызывающий процесс должен предоставить структуру hostent для заполнения, эта структура также указывает на другую информацию: каноническое имя, массив указателей на псевдонимы, строки псевдонимов, массив указателей на адреса и сами адреса (см., например, рис. 11.2). Вызывающий процесс должен предоставить один большой буфер, используемый для дополнительной информации, и заполняемая структура hostent будет содержать различные указатели на этот буфер. При этом добавляется как минимум три аргумента функции: указатель на заполняемую структуру hostent, указатель на буфер, используемый для всей прочей информации, и размер этого буфера. Требуется также четвертый дополнительный аргумент — указатель на целое число, в котором будет храниться код ошибки, поскольку глобальная целочисленная переменная h_errno больше не может использоваться. (Глобальная целочисленная переменная h_errno создает ту же проблему повторного вхождения, которая описана нами для переменной errno.)
Эта технология также используется функциями getnameinfo и inet_ntop.
2. Входящая функция вызывает функцию malloc и динамически выделяет память. Это технология, используемая функцией getaddrinfo. Проблема при таком подходе заключается в том, что приложение, вызывающее эту функцию, должно вызвать также функцию freeaddrinfo, чтобы освободить динамическую память. Если эта функция не вызывается, происходит утечка памяти: каждый раз, когда процесс вызывает функцию, выделяющую память, объем памяти, задействованной процессом, возрастает. Если процесс выполняется в течение длительного времени (что свойственно сетевым серверам), то потребление памяти этим процессом с течением времени неуклонно растет.
Обсудим функции Solaris 2.x, допускающие повторное вхождение, не используемые для сопоставления имен с адресами, и наоборот (то есть для разрешения имен).
#include <netdb.h>
struct hostent *gethostbyname_r(const char *hostname,
struct hostent *result, char *buf, int buflen, int *h_errnop);
struct hostent *gethostbyaddr_r(const char *addr, int len,
int type, struct hostent *result, char *buf, int buflen,
int *h_errnop);
Обе функции возвращают: непустой указатель в случае успешного выполнения, NULL в случае ошибки
Для каждой функции требуется четыре дополнительных аргумента. Аргумент result — это структура hostent, размещенная в памяти вызывающим процессом и заполняемая данной функцией. При успешном выполнении функции этот указатель также является возвращаемым значением.
Аргумент buf — это буфер, размещенный в памяти вызывающим процессом, a buflen — его размер. Буфер будет содержать каноническое имя, массив указателей на псевдонимы, строки псевдонимов, массив указателей на адреса и сами адреса. Все указатели в структуре hostent, на которую указывает result, указывают на этот буфер. Насколько большим должен быть этот буфер? К сожалению, все, что сказано в большинстве руководств, это что-то неопределенное вроде «Буфер должен быть достаточно большим, чтобы содержать все данные, связанные с записью узла». Текущие реализации функции gethostbyname могут возвращать до 35 указателей на альтернативные имена (псевдонимы), до 35 указателей на адреса и использовать буфер размером 8192 байт для хранения альтернативных имен (псевдонимов) и адресов. Поэтому буфер размером 8192 байт можно считать подходящим.
Если происходит ошибка, код ошибки возвращается через указатель h_errnop, а не через глобальную переменную h_errno.
ПРИМЕЧАНИЕ
К сожалению, проблема повторного вхождения гораздо серьезнее, чем может показаться. Во-первых, не существует стандарта относительно повторного вхождения и функций gethostbyname и gethostbyaddr. POSIX утверждает, что эти две функции не обязаны быть безопасными в многопоточной среде.
Во-вторых, не существует стандарта для функций _r. В этом разделе (в качестве примера) мы привели две функции _r, предоставляемые Solaris 2.x. В Linux присутствуют аналогичные функции, возвращающие hostent в качестве аргумента типа значение-результат. В Digital Unix и HP-UX имеются версии этих функций с другими аргументами. Первые два аргумента функции gethostbyname_r такие же, как и в версии Solaris, но оставшиеся три аргумента версии Solaris объединены в новую структуру hostent_data (которая должна быть размещена в памяти вызывающим процессом), а указатель на эту структуру — это третий и последний аргумент. Обычные функции gethostbyname и gethostbyaddr в Digital Unix 4.0 и в HP-UX 10.30 допускают повторное вхождение при использовании собственных данных потоков (см. раздел 23.5). Интересный рассказ о разработке функций _r Solaris 2.x содержится в [70].
Наконец, хотя версия функции gethostbyname, допускающая повторное вхождение, может обеспечить безопасность, когда ее одновременно вызывают несколько различных потоков, это ничего не говорит нам о возможности повторного вхождения для лежащих в ее основе функций распознавателя.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Функции
Функции Существует мнемоническое правило: функции не должны по объему кода превышать двух экранов текста и иметь больше десяти локальных переменных. Каждая функция должна выполнять одно действие, но делать это хорошо. Не вредно разбить функцию на последовательность
16.5.1. Функции
16.5.1. Функции Интерфейс termios определяет несколько функций. Все они объявлены в <termios.h>. Четыре из них являются обслуживающими функциями для переносимого манипулирования структурой struct termios; остальные представляют собой системные вызовы. Функции, начинающиеся с cf,
Функции
Функции Функции в JScript, как и в других алгоритмических языках, позволяют объединить несколько операций под одним именем. В случае необходимости функция может быть вызвана из любого места сценария.В сценариях JScript поддерживаются два вида функций: встроенные функции и
Функции GMP
Функции GMP ПодразделыФункции Введение Функции этого вида позволяют работать с целыми числами повышенной точности определенного формата используя библиотеку GNU MP.Эта библиотека не входит в стандартный пакет PHP. Загрузить коды библиотеки и документацию по ней можно на
5.8.7 Функции
5.8.7 Функции СинтаксисОболочка bash позволяет пользователю создавать собственные функции. Функции ведут себя и используются точно так же, как обычные команды оболочки, т. е. мы можем сами создавать новые команды. Функции конструируются следующим образом: function name () {list}Причем
19.7.8. Функции
19.7.8. Функции Описание функции выглядит так: имя() { список; }Пример:cdir(){ # изменяем каталог cd / }При выполнении функция не создает нового процесса, а выполняется в среде процесса, содержащего эту функцию. Аргументы функции можно передать ей как обыкновенные параметры при
10.16 Функции TCP
10.16 Функции TCP Данная глава посвящена многочисленным функциям TCP. Ниже перечислены основные из них:? Связывание портов с соединениями? Инициализация соединений посредством трехшагового подтверждения? Выполнение медленного старта, исключающего перегрузку
8.6. Функции
8.6. Функции Оператор определения функции имеет следующий синтаксис:[function] имя() { список}Определять функцию можно в любом месте сценария, но вызов ее должен осуществляться строго после описания. Вызывается функция подобно любой команде — по имени. Переданные ей аргументы
3.1. Функции
3.1. Функции Пример 1.7: Функция вычисляющая факториал.VAR A, Y : INTEGER;FUNCTION FAKTORIAL (N : INTEGER) : INTEGER; VAR F, K : INTEGER; BEGIN F := 1; FOR K := 1 TO N DO F := F * K; FAKTORIAL := F END; BEGINWRITELN (‘ВВЕДИТЕ ЦЕЛОЕ ПОЛОЖИТЕЛЬНОЕ ЧИСЛО’);READLN (A);Y := FAKTORIAL (A);WRITELN (‘N!=’, Y);READLN;READLNEND.Обратите внимание на то, что в описании функции
3. Функции
3. Функции В C есть только функции, а процедур нет.Тело функции не может содержать в себе определения других функций.Функцию можно вызвать из другой функции.Оператор return возвращает выполнение программы в точку вызова функции.При использовании return; функция
4.5.3. Функции, которые создают новые конфигурации из существующих 4.5.3.1. Функции геометрии, которые производят новые конфигурации
4.5.3. Функции, которые создают новые конфигурации из существующих 4.5.3.1. Функции геометрии, которые производят новые конфигурации Раздел "4.5.2. Функции Geometry" обсуждает несколько функций, которые создают новые конфигурации из
Функции
Функции Excel – серьезная программа для вычислений, одним из главных достоинств которой является множество встроенных функций. Это обширная тема, достойная если не книги, то главы в многотомном руководстве. Рассмотрим ее кратко – ровно настолько, чтобы вы могли далее
Функции
Функции AddAtom Функция AddAtom добавляет строку символов в таблицу локальных атомов и возвращает уникальное значение (атом), идентифицирующее строку. ATOM AddAtom ( LPCTSTR lpString // указатель на добавляемую строку ); Параметры lpString - указатель на добавляемую строку, завершающуюся нулем.
1.5 Функции
1.5 Функции Функция – это именованная часть программы, к которой можно обращаться из других частей программы столько раз, сколько потребуется. Рассмотрим программу, печатающую степени числа 2:extern float pow(float, int); //pow() определена в другом местеmain() (* for (int i=0; i«10; i++) cout „« pow(2,i) ««