- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания UNIX: взаимодействие процессов - Уильям Стивенс
Шрифт:
Интервал:
Закладка:
ПРИМЕЧАНИЕ
Впервые двери были разработаны для распределенной операционной системы Spring. Детали этого проекта доступны по адресу http://www.sun.com/tech/projects/spring. Описание механизма дверей в этой операционной системе можно найти в книге [7].
Затем двери появились в версии Solaris 2.5, хотя единственная страница документации, к ним относящаяся, содержала только предупреждение о том, что двери являются экспериментальным интерфейсом, используемым отдельными приложениями Sun. В Solaris 2.6 описание этого интерфейса занимает уже 8 страниц, но в них он характеризуется как «развивающийся». В будущих версиях Solaris 2.6 описываемый в этой главе интерфейс API может быть изменен. Предварительная версия дверей для Linux уже разрабатывается, детали можно выяснить по адресу http://www.cs.brown.edu/~tor/doors.
Чтобы воспользоваться интерфейсом дверей в Solaris 2.6, нужно подключить соответствующую библиотеку (-ldoor), содержащую функции door_XXX, описываемые в этой главе, и использовать файловую систему ядра (/kernel/sys/doorfs).
Хотя двери поддерживаются только в системе Solaris, мы описываем их достаточно подробно, поскольку это описание позволяет подготовить читателя к удаленному вызову процедур без необходимости обсуждать какие-либо детали сетевого интерфейса. В приложении А мы увидим, что этот интерфейс достаточно быстр — едва ли не быстрее, чем все остальные средства передачи сообщений.
Локальные вызовы процедур являются синхронными (synchronous): вызывающий процесс не получает управление до тех пор, пока не происходит возврат из вызванной процедуры. Потоки могут восприниматься как средство асинхронного вызова процедур: функция (указанная в третьем аргументе pthread_create) выполняется одновременно с вызвавшим процессом. Вызвавший процесс может ожидать завершения вызванного процесса с помощью функции pthread_join. Удаленный вызов процедур может быть как синхронным, так и асинхронным, но мы увидим, что вызовы через двери являются синхронными.
Внутри процесса двери идентифицируются дескрипторами. Извне двери могут идентифицироваться именами в файловой системе. Сервер создает дверь вызовом door_create; аргументом этой функции является указатель на процедуру, которая будет связана с данной дверью, а возвращаемое значение является дескриптором двери. Затем сервер связывает полное имя файла с дескриптором двери с помощью функции fattach. Клиент открывает дверь вызовом open, при этом аргументом функции является полное имя файла, которое сервер связал с дверью, а возвращаемым значением — дескриптор, который будет использоваться клиентом для доступа к двери. Затем клиент может вызывать процедуру с помощью door_call. Естественно, программа, являющаяся сервером для некоторой двери, может являться клиентом для другой.
Мы уже сказали, что вызовы через двери являются синхронными: когда клиент вызывает door_call, возврата из этой функции не происходит до тех пор, пока процедура на сервере не завершит работу (возможно, с ошибкой). Реализация дверей в Solaris связана с потоками. Каждый раз, когда клиент вызывает процедуру сервера, для обработки этого вызова создается новый поток в процессе-сервере. Работа с потоками обычно осуществляется автоматически функциями библиотеки дверей, при этом потоки создаются по мере необходимости, но мы увидим, что сервер может и сам управлять этими потоками, если это требуется. Это также означает, что одна и та же процедура может выполняться сервером для нескольких клиентов, причем для каждого из них будет создан отдельный поток. Такой сервер является параллельным. Поскольку одновременно могут выполняться несколько экземпляров процедуры сервера (каждая из которых представляет собой отдельный поток), содержимое этих процедур должно соответствовать определенным требованиям, которые обычно предъявляются к многопоточным программам.
При удаленном вызове процедуры и данные, и дескрипторы могут быть переданы от клиента к серверу. Обратно также могут быть переданы данные и дескрипторы. Передача дескрипторов вообще является неотъемлемым свойством дверей. Более того, поскольку двери идентифицируются дескрипторами, это позволяет процессу передать дверь другому процессу. Более подробно о передаче дескрипторов будет говориться в разделе 15.8.
Пример
Начнем описание интерфейса дверей с простого примера: клиент передает серверу длинное целое, а сервер возвращает клиенту квадрат этого значения тоже как длинное целое. В листинге 15.1[1] приведен текст программы-клиента (в этом примере мы опускаем множество деталей, большую часть которых мы обсудим далее в тексте главы).
Листинг 15.1 .Клиент передает серверу длинное целое для возведения его в квадрат//doors/client1.c
1 #include "unpipc.h"
2 int
3 main(int argc, char **argv)
4 {
5 int fd;
6 long ival, oval;
7 door_arg_t arg;
8 if (argc != 3)
9 err_quit("usage: client1 <server-pathname> <integer-value>");
10 fd = Open(argv[1], O_RDWR); /* открываем дверь */
11 /* задаем аргументы и указатель на результат */
12 ival = atol(argv[2]);
13 arg.data_ptr = (char *) &ival; /* аргументы */
14 arg.data_size = sizeof(long); /* размер аргументов */
15 arg.desc_ptr = NULL;
16 arg.desc_num = 0;
17 arg.rbuf = (char *) &oval; /* результат */
18 arg.rsize = sizeof(long); /* размер результата */
19 /* вызываем процедуру на сервере и выводим результат */
20 Door_call(fd, &arg);
21 printf("result: %ldn", oval);
22 exit(0);
23 }
Открываем дверь8-10 Дверь задается полным именем, передаваемым в качестве аргумента командной строки. Она открывается вызовом open. Возвращаемый дескриптор называется дескриптором двери, но часто его самого и называют дверью.
Подготовка аргументов и указателя на результат11-18 Структура arg содержит указатели на аргументы и результат. Поле data_ptr указывает на первый байт аргументов, a data_size содержит количество байтов в аргументах. Два поля desc_ptr и desc_num предназначены для передачи дескрипторов, о чем мы будем подробно говорить в разделе 15.8. rbuf указывает на первый байт буфера результата, a rsize задает его размер.
Вызов процедуры на сервере и вывод результата19-21 Мы вызываем процедуру на сервере с помощью door_call; аргументами этого вызова являются дескриптор двери и указатель на структуру аргументов. После возвращения из этого вызова программа печатает получившийся результат.
Программа-сервер приведена в листинге 15.2. Она состоит из процедуры сервера с именем servproc и функции main.
Листинг 15.2. Сервер, возводящий длинное целое в квадрат//doors/server1.c
1 #include "unpipc.h"
2 void
3 servproc(void *cookie, char *dataptr, size_t datasize,
4 door_desc_t *descptr, size_t ndesc)
5 {
6 long arg, result;
7 arg = *((long *) dataptr);
8 result = arg * arg;
9 Door_return((char *) &result, sizeof(result), NULL, 0);
10 }
11 int
12 main(int argc, char **argv)
13 {
14 int fd;
15 if (argc != 2)
16 err_quit("usage: server1 <server-pathname>");
17 /* создание двери и связывание ее с файлом */
18 fd = Door_create(servproc, NULL, 0);
19 unlink(argv[1]);
20 Close(Open(argv[1], O_CREAT | O_RDWR, FILE_MODE));
21 Fattach(fd, argv[1]);
22 /* функция servproc() обрабатывает все запросы клиентов */
23 for (;;)
24 pause();
25 }
Процедура сервера2-10 Процедура сервера вызывается с пятью аргументами, но мы используем только один из них — dataptr. Он указывает на первый байт аргумента. Аргумент, представляющий собой длинное целое, передается через этот указатель и возводится в квадрат. Управление передается клиенту вместе с результатом вызовом door_return. Первый аргумент указывает на результат, второй задает его размер, а оставшиеся предназначены для возврата дескрипторов.
Создание дескриптора двери и связывание с ним файла17-21 Дескриптор двери создается вызовом door_create. Первый аргумент является указателем на функцию, соответствующую этой двери (servproc). После получения этого дескриптора его нужно связать с некоторым именем в файловой системе, поскольку оно будет использоваться клиентом для подключения к этой двери. Делается это путем создания обычного файла в файловой системе (сначала мы вызываем unlink, на тот случай, если такой файл уже существует, причём возможная ошибка игнорируется) и вызова fattach — функции SVR4, связывающей дескриптор с полным именем файла.
Главный поток сервера ничего не делает22-24 Главный поток сервера блокируется при вызове pause. Вся функциональность обеспечивается функцией servproc, которая будет запускаться как отдельный поток каждый раз при получении запроса клиента.