Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

С помощью метода, аналогичного применяемому для сервера NTP, был изменен эхо-сервер UDP для работы с вводом-выводом, управляемым сигналом: мы стремимся выполнить чтение дейтаграммы как можно быстрее после ее прибытия, чтобы получить точную отметку времени прибытия и поставить дейтаграмму в очередь для дальнейшей обработки.

Упражнения

1. Далее приведен альтернативный вариант цикла, рассмотренного в листинге 25.2:

for (;;) {

Sigprocmask(SIG_BLOCK, &newmask, &oldmask);

while (nqueue == 0)

sigsuspend(&zeromask); /* ожидание дейтаграммы для обработки */

nqueue--;

/* разблокирование SIGIO */

Sigprocmask(SIG_SETMASK, &oldmask, NULL);

Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,

dg[iget].dg_sa, dg[iget].dg_salen);

if (++iget >= QSIZE)

iget = 0;

}

Верна ли такая модификация?

Глава 26

Программные потоки

26.1. Введение

Согласно традиционной модели Unix, когда процессу требуется, чтобы некое действие было выполнено каким-либо другим объектом, он порождает дочерний процесс, используя функцию

fork
, и этим порожденным процессом выполняется необходимое действие. Большинство сетевых серверов под Unix устроены именно таким образом, как мы видели при рассмотрении примера параллельного (concurrent) сервера: родительский процесс осуществляет соединение с помощью функции
accept
и порождает дочерний процесс, используя функцию
fork
, а затем дочерний процесс занимается обработкой клиентского запроса.

Хотя эта концепция с успехом использовалась на протяжении многих лет, с функцией

fork
связаны определенные неудобства.

Стоимость функции

fork
довольно высока, так как при ее использовании требуется скопировать все содержимое памяти из родительского процесса в дочерний, продублировать все дескрипторы и т.д. Текущие реализации используют технологию, называемую копированием при записи( copy-on-write), при которой копирование пространства данных из родительского процесса в дочерний происходит лишь тогда, когда дочернему процессу требуется своя собственная копия. Но несмотря на эту оптимизацию, стоимость функции
fork
остается высокой.

Для передачи данных между родительским и дочерним процессами послевызова функции

fork
требуется использовать средства взаимодействия процессов (IPC). Передача информации перед вызовом
fork
не вызывает затруднений, так как при запуске дочерний процесс получает от родительского копию пространства данных и копии всех родительских дескрипторов. Но возвращение информации из дочернего процесса в родительский требует большей работы.

Обе проблемы могут быть разрешены путем использования программных потоков( threads). Программные потоки иногда называются облегченными процессами( lightweight processes), так как поток проще, чем процесс. В частности, создание потока требует в 10–100 раз меньше времени, чем создание процесса.

Все потоки одного процесса совместно используют его глобальные переменные, поэтому им легко обмениваться информацией, но это приводит к необходимости синхронизации.

Однако общими становятся не только глобальные переменные. Все потоки одного процесса разделяют:

инструкции процесса;

большую часть данных;

открытые файлы (например, дескрипторы);

обработчики сигналов и вообще настройки для работы с сигналами (действие сигнала);

текущий рабочий каталог;

идентификаторы пользователя и группы пользователей.

У каждого потока имеются собственные:

идентификатор потока;

набор регистров, включая счетчик команд и указатель стека;

стек (для локальных переменных и адресов возврата);

переменная

errno
;

маска сигналов;

приоритет.

ПРИМЕЧАНИЕ

Как сказано в разделе 11.18, можно рассматривать обработчик сигнала как некую разновидность потока. В традиционной модели Unix у нас имеется основной поток выполнения и обработчик сигнала (другой поток). Если в основном потоке в момент возникновения сигнала происходит корректировка связного списка и обработчик сигнала также пытается изменить связный список, обычно начинается путаница. Основной поток и обработчик сигнала совместно используют одни и те же глобальные переменные, но у каждого из них имеется свой собственный стек.

В этой книге мы рассматриваем потоки POSIX, которые также называются Pthreads(POSIX threads). Они были стандартизованы в 1995 году как часть POSIX.1c и будут поддерживаться большинством версий Unix. Мы увидим, что все названия функций Pthreads начинаются с символов

pthread_
. Эта глава является введением в концепцию потоков, необходимым для того, чтобы в дальнейшем мы могли использовать потоки в наших сетевых приложениях. Более подробную информацию вы можете найти в [15].

  • Читать дальше
  • 1
  • ...
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: