30.8. Сервер TCP с предварительным порождением процессов и защитой вызова accept при помощи взаимного исключения
30.8. Сервер TCP с предварительным порождением процессов и защитой вызова accept при помощи взаимного исключения
Как мы уже говорили, существует несколько способов синхронизации процессов путем блокирования. Блокировка файла по стандарту POSIX, рассмотренная в предыдущем разделе, переносится на все POSIX-совместимые системы, но она подразумевает некоторые операции с файловой системой, которые могут потребовать времени. В этом разделе мы будем использовать блокировку при помощи взаимного исключения, обладающую тем преимуществом, что ее можно применять для синхронизации не только потоков внутри одного процесса, но и потоков, относящихся к различным процессам.
Функция main остается такой же, как и в предыдущем разделе, то же относится к функциям child_make и child_main. Меняются только три функции, осуществляющие блокировку. Чтобы использовать взаимное исключение между различными процессами, во-первых, требуется хранить это взаимное исключение в разделяемой процессами области памяти, а во-вторых, библиотека потоков должна получить указание о том, что взаимное исключение совместно используется различными процессами.
ПРИМЕЧАНИЕ
Требуется также, чтобы библиотека потоков поддерживала атрибут PTHREAD_PROCESS_SHARED.
Существует несколько способов разделения памяти между различными процессами, что мы подробно описываем во втором томе[2] данной серии. В этом примере мы используем функцию mmap с устройством /dev/zero, которое работает с ядрами Solaris и другими ядрами SVR4. В листинге 30.14 показана только функция my_lock_init.
Листинг 30.14. Функция my_lock_init: использование взаимного исключения потоками, относящимися к различным процессам (технология Pthread)
//server/lock_pthread.c
1 #include "unpthread.h"
2 #include <sys/mman.h>
3 static pthread_mutex_t *mptr; /* фактически взаимное исключение будет
в совместно используемой памяти */
4 void
5 my_lock_init(char *pathname)
6 {
7 int fd;
8 pthread_mutexattr_t mattr;
9 fd = Open("/dev/zero", O_RDWR, 0);
10 mptr = Mmap(0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE,
11 MAP_SHARED, fd, 0);
12 Close(fd);
13 Pthread_mutexattr_init(&mattr);
14 Pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
15 Pthread_mutex_init(mptr, &mattr);
16 }
9-12 Мы открываем (open) файл /dev/zero, а затем вызываем mmap. Количество байтов (второй аргумент этой функции) — это размер переменной pthread_mutex_t. Затем дескриптор закрывается, но для нас это не имеет значения, так как файл уже отображен в память.
13-15 В приведенных ранее примерах взаимных исключений Pthread мы инициализировали глобальные статические взаимные исключения, используя константу PTHREAD_MUTEX_INITIALIZER (см., например, листинг 26.12). Но располагая взаимное исключение в совместно используемой памяти, мы должны вызвать некоторые библиотечные функции Pthreads, чтобы сообщить библиотеке о наличии семафора в совместно используемой памяти и о том, что он будет применяться для синхронизации потоков, относящихся к различным процессам. Мы должны инициализировать структуру pthread_mutexattr_t задаваемыми по умолчанию атрибутами взаимного исключения, а затем установить значение атрибута PTHREAD_PROCESS_SHARED. (По умолчанию значением этого атрибута должно быть PTHREAD_PROCESS_PRIVATE, что подразумевает использование взаимного исключения только в пределах одного процесса.) Затем вызов pthread_mutex_init инициализирует взаимное исключение указанными атрибутами.
В листинге 30.15 показаны только функции my_lock_wait и my_lock_release. Они содержат вызовы функций Pthreads, предназначенных для блокирования и разблокирования взаимного исключения.
Листинг 30.15. Функции my_lock_wait и my_lock_release: использование блокировок Pthread
//server/lock_pthread.c
17 void
18 my_lock_wait()
19 {
20 Pthread_mutex_lock(mptr),
21 }
22 void
23 my_lock_release()
24 {
25 Pthread_mutex_unlock(mptr);
26 }
Сравнивая строки 3 и 4 табл. 30.1, можно заметить, что версия, использующая синхронизацию процессов при помощи взаимного исключения, характеризуется более высоким быстродействием, чем версия с блокировкой файла.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Совет 64: Учеба под защитой
Совет 64: Учеба под защитой Когда юный Михаил Ломоносов шел через всю Россию учиться наукам, для защиты от лихих людей ему пришлось присоединиться к рыбному обозу. Прошло 300 лет, путь к знаниям стал легче и проще, но едва ли безопаснее. Интернет быстро снабдит пытливый ум
Семантика вызова
Семантика вызова Вызов локальной процедуры однозначно приводит к ее выполнению, после чего управление возвращается в головную программу. Иначе дело обстоит при вызове удаленной процедуры. Невозможно установить, когда конкретно будет выполняться процедура, будет ли она
4.6. Функция accept
4.6. Функция accept Функция accept вызывается сервером TCP для возвращения следующего установленного соединения из начала очереди полностью установленных соединений (см. рис. 4.2). Если очередь полностью установленных соединений пуста, процесс переходит в состояние ожидания (по
5.11. Прерывание соединения перед завершением функции accept
5.11. Прерывание соединения перед завершением функции accept Существует другое условие, аналогичное прерванному системному вызову, пример которого был описан в предыдущем разделе. Оно может привести к возвращению функцией accept нефатальной ошибки, в случае чего следует
16.6. Неблокируемая функция accept
16.6. Неблокируемая функция accept Как было сказано в главе 6, функция select сообщает, что прослушиваемый сокет готов для чтения, когда установленное соединение готово к обработке функцией accept. Следовательно, если мы используем функцию select для определения готовности входящих
30.6. Сервер TCP с предварительным порождением процессов без блокировки для вызова accept
30.6. Сервер TCP с предварительным порождением процессов без блокировки для вызова accept В первом из рассматриваемых нами «усовершенствованных» серверов используется технология, называемая предварительным созданием процессов (preforking). Вместо того чтобы вызывать функцию fork
30.7. Сервер TCP с предварительным порождением процессов и защитой вызова accept блокировкой файла
30.7. Сервер TCP с предварительным порождением процессов и защитой вызова accept блокировкой файла Описанная выше реализация, позволяющая нескольким процессам вызывать функцию accept на одном и том же прослушиваемом дескрипторе, возможна только для систем 4.4BSD, в которых функция
30.9. Сервер TCP с предварительным порождением процессов: передача дескриптора
30.9. Сервер TCP с предварительным порождением процессов: передача дескриптора Последней модификацией нашего сервера с предварительным порождением процессов является версия, в которой только родительский процесс вызывает функцию accept, а затем «передает» присоединенный
30.11. Сервер TCP с предварительным порождением потоков, каждый из которых вызывает accept
30.11. Сервер TCP с предварительным порождением потоков, каждый из которых вызывает accept Ранее в этой главе мы обнаружили, что версии, в которых заранее создается пул дочерних процессов, работают быстрее, чем те, в которых для каждого клиентского запроса приходится вызывать
30.12. Сервер с предварительным порождением потоков: основной поток вызывает функцию accept
30.12. Сервер с предварительным порождением потоков: основной поток вызывает функцию accept Последняя рассматриваемая нами версия сервера устроена следующим образом: главный поток создает пул потоков при запуске сервера, после чего он же вызывает функцию accept и передает
16.14. Сервер kHTTPd — веб-сервер уровня ядра
16.14. Сервер kHTTPd — веб-сервер уровня ядра В операционной системе все процессы можно разделить на два типа: процессы уровня ядра и пользовательские процессы. Процесс уровня ядра запускается и работает очень быстро по сравнению с относительно неповоротливым
6.5.1. Действие ACCEPT
6.5.1. Действие ACCEPT Данная операция не имеет дополнительных ключей. Если над пакетом выполняется действие ACCEPT, то пакет прекращает движение по цепочке (и всем вызвавшим цепочкам, если текущая цепочка была вложенной) и считается ПРИНЯТЫМ (то бишь пропускается), тем не менее,
С защитой от воды
С защитой от воды Автор: Олег ВолошинНечасто бывает, что названия некоторых ноутбуков ассоциируются с прочностью. Серия Panasonic Toughbook - как раз тот самый случай, благо большинство из нас слышало про защищенные модели ноутбуков этой уважаемой фирмы. Посему я чрезвычайно
Стивенс Уильям Ричард
Просмотр ограничен
Смотрите доступные для ознакомления главы 👉