UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Коллизии при вызове функции select
Рассматривая данный пример в 4.4BSD, мы можем исследовать еще одну проблему, которая встречается довольно редко и поэтому часто остается непонятой до конца. В разделе 16.13 [128] говорится о коллизиях (collisions), возникающих при вызове функции
select
socket
select
Коллизии при вызове функции
select
accept
select
select
child_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
nselcoll
select
Если сравнить значения времени, затраченного центральным процессором в этом примере, то получится, что при добавлении вызова функции
select
accept
select
Из этого примера следует вывод, что когда несколько процессов блокируются на одном и том же дескрипторе, лучше, чтобы эта блокировка была связана с функцией
accept
select
30.7. Сервер TCP с предварительным порождением процессов и защитой вызова accept блокировкой файла
Описанная выше реализация, позволяющая нескольким процессам вызывать функцию
accept
accept
accept
EPROTO
Причины возникновения этой проблемы с библиотечной версией функции accept в SVR4 связаны с реализацией потоков STREAMS и тем фактом, что библиотечная функция accept не является атомарной операцией. В Solaris 2.6 эта проблема решена, но в большинстве реализаций SVR4 она остается.
Решением этой проблемы является защита вызова функции
accept
accept
Существует несколько способов реализации защиты вызова функции
accept
fcntl
Единственным изменением в функции
main
my_lock_init
+ my_lock_init("/tmp/lock.XXXXXX"); /* один файл для всех дочерних
процессов */
for (i = 0; i < nchildren; i++)
pids[i] = child_make(i, listenfd, addrlen); /* возвращение
родительского процесса */
Функция
child_make
child_main
accept
for (;;) {
clilen = addrlen;
+ my_lock_wait();
connfd = Accept(listenfd, cliaddr, &clilen);
+ my_lock_release();
web_child(connfd); /* обработка запроса */
Close(connfd);
}
В листинге 30.12 показана наша функция
my_lock_init