UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Коллизии при вызове функции select
Рассматривая данный пример в 4.4BSD, мы можем исследовать еще одну проблему, которая встречается довольно редко и поэтому часто остается непонятой до конца. В разделе 16.13 [128] говорится о коллизиях (collisions), возникающих при вызове функции
selectsocketselectКоллизии при вызове функции
selectacceptselectselectchild_main+Листинг 30.11. Модификация листинга 30.9: блокирование в вызове select вместо блокирования в вызове accept
printf("child %ld startingn", (long)getpid());+ FD_ZERO(&rset); for (;;) {+ FD_SET(listenfd, &rset);+ Select(listenfd+1, &rset, NULL, NULL, NULL);+ if (FD_ISSET(listenfd, &rset) == 0)+ err_quit("listenfd readable");+ clilen = addrlen; connfd = Accept(listenfd, cliaddr, &clilen); web_child(connfd); /* обработка запроса */ Close(connfd); }Если, проделав это изменение, мы проверим значение счетчика ядра BSD/OS
nselcollselectЕсли сравнить значения времени, затраченного центральным процессором в этом примере, то получится, что при добавлении вызова функции
selectacceptselectИз этого примера следует вывод, что когда несколько процессов блокируются на одном и том же дескрипторе, лучше, чтобы эта блокировка была связана с функцией
acceptselect30.7. Сервер TCP с предварительным порождением процессов и защитой вызова accept блокировкой файла
Описанная выше реализация, позволяющая нескольким процессам вызывать функцию
acceptacceptacceptEPROTOПричины возникновения этой проблемы с библиотечной версией функции accept в SVR4 связаны с реализацией потоков STREAMS и тем фактом, что библиотечная функция accept не является атомарной операцией. В Solaris 2.6 эта проблема решена, но в большинстве реализаций SVR4 она остается.
Решением этой проблемы является защита вызова функции
acceptacceptСуществует несколько способов реализации защиты вызова функции
acceptfcntlЕдинственным изменением в функции
mainmy_lock_init+ my_lock_init("/tmp/lock.XXXXXX"); /* один файл для всех дочерних процессов */ for (i = 0; i < nchildren; i++) pids[i] = child_make(i, listenfd, addrlen); /* возвращение родительского процесса */Функция
child_makechild_mainaccept for (;;) { clilen = addrlen;+ my_lock_wait(); connfd = Accept(listenfd, cliaddr, &clilen);+ my_lock_release(); web_child(connfd); /* обработка запроса */ Close(connfd); }В листинге 30.12 показана наша функция
my_lock_init
