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

<p>30.7. Сервер TCP с предварительным порождением процессов и защитой вызова accept блокировкой файла</p>

Описанная выше реализация, позволяющая нескольким процессам вызывать функцию acceptна одном и том же прослушиваемом дескрипторе, возможна только для систем 4.4BSD, в которых функция acceptреализована внутри ядра. Ядра системы SVR4, в которых accept реализована как библиотечная функция, не допускают этого. В самом деле, если мы запустим сервер из предыдущего раздела, в котором имеется несколько дочерних процессов, в Solaris 2.5 (система SVR4), то вскоре после того, как клиенты начнут соединяться с сервером, вызов функции acceptв одном из дочерних процессов вызовет ошибку EPROTO, что свидетельствует об ошибке протокола.

ПРИМЕЧАНИЕ

Причины возникновения этой проблемы с библиотечной версией функции accept в SVR4 связаны с реализацией потоков STREAMS и тем фактом, что библиотечная функция accept не является атомарной операцией. В Solaris 2.6 эта проблема решена, но в большинстве реализаций SVR4 она остается.

Решением этой проблемы является защита вызова функции acceptпри помощи блокировки, так что в данный момент времени только один процесс может быть блокирован в вызове этой функции. Другие процессы также будут блокированы, так как они будут стремиться установить блокировку для вызова функции accept.

Существует несколько способов реализации защиты вызова функции accept, о которых рассказывается во втором томе [2]данной серии. В этом разделе мы используем блокировку файла функцией fcntlсогласно стандарту POSIX.

Единственным изменением в функции main(см. листинг 30.6) будет добавление вызова функции my_lock_initперед началом цикла, в котором создаются дочерние процессы:

+ my_lock_init("/tmp/lock.XXXXXX"); /* один файл для всех дочерних

                                       процессов */

  for (i = 0; i nchildren; i++)

   pids[i] = child_make(i, listenfd, addrlen); /* возвращение

                                       родительского процесса */

Функция child_makeостается такой же, как в листинге 30.8. Единственным изменением функции child_main(см. листинг 30.9) является блокирование перед вызовом функции 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, в которой используется блокировка файла согласно стандарту POSIX.

Листинг 30.12. Функция my_lock_init: блокировка файла

//server/lock_fcntl.c

 1 #include "unp.h"

 2 static struct flock lock_it, unlock_it;

 3 static int lock_fd = -1;

 4 /* fcntl не выполнится, если не будет вызвана функция my_lock_init */

 5 void

 6 my_lock_init(char *pathname)

 7 {

 8  char lock_file[1024];

 9  /* копируем строку вызывающего процесса на случай, если это константа */

10  strncpy(lock_file, pathname, sizeof(lock_file));

11  lock_fd = Mkstemp(lock_file);

12  Unlink(lock_file); /* но lock_fd остается открытым */

13  lock_it.l_type = F_WRLCK;

14  lock_it.l_whence = SEEK_SET;

15  lock_it.l_start = 0;

16  lock_it.l_len = 0;

17  unlock_it.l_type = F_UNLCK;

18  unlock_it.l_whence = SEEK_SET;

19  unlock_it.l_start = 0;

20  unlock_it.l_len = 0;

21 }

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT