Уильям Стивенс - UNIX: разработка сетевых приложений

Тут можно читать онлайн Уильям Стивенс - UNIX: разработка сетевых приложений - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Питер, год 2007. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: разработка сетевых приложений
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2007
  • Город:
    Санкт-Петербург
  • ISBN:
    5-94723-991-4
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание

UNIX: разработка сетевых приложений - описание и краткое содержание, автор Уильям Стивенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок

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. О них рассказывается в следующем разделе.

В качестве альтернативы некоторые реализации с поддержкой программных потоков (Digital Unix 4.0 и HP_UX 10.30) предоставляют версии этих функций, допускающие повторное вхождение за счет использования собственных данных программных потоков.

■ Функции inet_ptonи inet_ntopвсегда допускают повторное вхождение.

■ Исторически функция inet_ntoaне допускает повторное вхождение, но некоторые реализации с поддержкой потоков предоставляют версию, допускающую повторное вхождение, которая строится на основе собственных данных потоков.

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

■ Функция getnameinfoдопускает повторное вхождение, только если она сама вызывает такие функции, то есть если она вызывает соответствующую версию функции gethostbyaddrдля получения имени узла или функции getservbyportдля получения имени службы. Обратите внимание, что обе результирующих строки (для имени узла и для имени службы) размещаются в памяти вызывающим процессом, чтобы обеспечить возможность повторного вхождения.

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

■ поместить аргумент системного вызова (целочисленный дескриптор) в регистр;

■ поместить значение в другой регистр, указывая, что был сделан системный вызов функции close;

■ активизировать системный вызов (переключиться на ядро со специальной инструкцией);

■ проверить значение регистра, чтобы увидеть, что произошла ошибка;

■ если ошибки нет, возвратить (0);

■ сохранить значение какого-то другого регистра в переменной errno;

■ возвратить (-1).

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

Будем считать, что программа проверяет возвращаемое значение функции closeи затем выводит значение переменной errno, если произошла ошибка, как в следующем примере:

if (close(fd) < 0) {

fprintf(stderr, "close error, errno = $d\n", errno);

exit(1);

}

Существует небольшой промежуток времени между сохранением кода ошибки в переменной errno в тот момент, когда системный вызов возвращает управление, и выводом этого значения программой. В течение этого промежутка другой программный поток внутри процесса (то есть обработчик сигналов) может изменить значение переменной errno. Если, например, при вызове обработчика сигналов главный поток управления находится между closeи fprintfи обработчик сигналов делает какой-то другой системный вызов, возвращающий ошибку (допустим, вызывается функция write), то значение переменной errno, записанное при вызове функции close, заменяется на значение, записанное при вызове функции write.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




UNIX: разработка сетевых приложений отзывы


Отзывы читателей о книге UNIX: разработка сетевых приложений, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x