Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

Можно объединять несколько флагов путем логического сложения, если их сочетание имеет смысл, например

NI_DGRAM
и
NI_NUMERICHOST
.

11.18. Функции, допускающие повторное вхождение

Функция

gethostbyname
из раздела 11.3 имеет интересную особенность, которую мы еще не рассматривали: она не допускает повторное вхождение (nonreentrant). Мы еще столкнемся с этой проблемой в главе 23, когда будем обсуждать потоки, но не менее интересно найти решение этой проблемы сейчас, без необходимости обращаться к понятию потоков.

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

gethostbyname
, и
gethostbyaddr
— содержатся в одном файле, который имеет следующий вид:

staticstruct hostent host; /* здесь хранится результат */

struct hostent*

gethostbyname(const char *hostname) {

return(gethostbyname2(hostname, family));

}

struct hostent*

gethostbyname2(const char *hostname, int family) {

/* вызов функций DNS для запроса А или AAAA */

/* заполнение структуры адреса узла */

return(&host);

}

struct hostent*

gethostbyaddr(const char *addr, size_t len, int family) {

/* вызов функций DNS для запроса PTR в домене in-addr.arpa */

/* заполнение структуры адреса узла */

return(&host);

}

Мы выделили полужирным шрифтом спецификатор класса памяти

static
итоговой структуры, потому что основная проблема в нем. Тот факт, что эти три функции используют общую переменную
host
, представляет другую проблему, которую мы обсудим в упражнении 11.1. (Вспомните табл. 11.4.) Функция
gethostbyname2
появилась в BIND 4.9.4 с добавлением поддержки IPv6. Мы будем игнорировать тот факт, что когда мы вызываем функцию
gethostbyname
, задействуется функция
gethostbyname2
, поскольку это не относится к предмету обсуждения.

Проблема повторного вхождения может возникнуть в нормальном процессе Unix, вызывающем функцию

gethostbyname
или
gethostbyaddr
и из управляющего элемента главного потока, и из обработчика сигнала. Когда вызывается обработчик сигнала (допустим, это сигнал
SIGALRM
, который генерируется раз в секунду), главный поток управляющего элемента процесса временно останавливается и вызывается функция обработки сигнала. Рассмотрим следующую ситуацию:

main {

struct hostent *hptr;

...

signal(SIGALRM, sig_alrm);

...

hptr = gethostbyname( ... );

...

}

void

sig_alrm(int signo) {

struct hostent *hptr;

...

hptr = gethostbyname( ... );

...

}

Если главный поток управления в момент остановки находится в середине выполнения функции

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

Если мы посмотрим на функции преобразования имен и адресов, представленные в этой главе и в главе 9, вместе с функциями

inet_ XXX
из главы 4, мы заметим следующее:

Функции

gethostbyname
,
gethostbyname2
,
gethostbyaddr
,
getservbyname
и
getservbyport
традиционно не допускают повторного вхождения, поскольку все они возвращают указатель на статическую структуру.

Некоторые реализации, поддерживающие программные потоки (Solaris 2.x), предоставляют версии этих четырех функций, допускающие повторное вхождение, с именами, оканчивающимися суффиксом

_r
. О них рассказывается в следующем разделе.

  • Читать дальше
  • 1
  • ...
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: