Уильям Стивенс - UNIX: взаимодействие процессов
- Название:UNIX: взаимодействие процессов
- Автор:
- Жанр:
- Издательство:Питер
- Год:2003
- Город:Санкт-Петербург
- ISBN:5-318-00534-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: взаимодействие процессов краткое содержание
Книга написана известным экспертом по операционной системе UNIX и посвящена описанию одной из форм межпроцессного взаимодействия, IPC, с использованием которой создается большинство сложных программ. В ней описываются четыре возможности разделения решаемых задач между несколькими процессами или потоками одного процесса: передача сообщений, синхронизация, разделяемая память, удаленный вызов процедур.
Книга содержит большое количество иллюстрирующих примеров и может использоваться как учебник по IPC, и как справочник для опытных программистов.
UNIX: взаимодействие процессов - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
■ PIPE_BUF — максимальное количество данных, для которого гарантируется атомарность операции записи (описано в разделе 4.7; Posix требует по меньшей мере 512 байт).
Значение OPEN_MAX можно узнать, вызвав функцию sysconf, как мы вскоре покажем. Обычно его можно изменить из интерпретатора команд с помощью команды ulimit (в Bourne shell и KornShell, как мы вскоре покажем) или с помощью команды limit (в С shell). Оно может быть изменено и самим процессом с помощью вызова функции setrlimit (подробно описана в разделе 7.11 [21]).
Значение PIPE_BUF обычно определено в заголовочном файле , но с точки зрения стандарта Posix оно представляет собой переменную, зависимую от полного имени файла. Это означает, что ее значение может меняться в зависимости от указываемого имени файла (для FIFO, поскольку каналы имен не имеют), поскольку разные имена могут относиться к разным файловым системам и эти файловые системы могут иметь различные характеристики. Это значение можно получить в момент выполнения пpoгрaммы, вызвав либо pathconf, либо fpathconf. В листинге 4.17 приведен пример, выводящий текущее значение этих двух oгрaничeний.
//pipe/pipeconf.c
1 #include "unpipc.h"
2 int
3 main(int argc, char **argv)
4 {
5 if (argc != 2)
6 err_quit("usage: pipeconf ");
7 printf("PIPE_BUF = %ld. OPEN_MAX = %ld\n",
8 Pathconf(argv[1], _PC_PIPE_BUF), Sysconf(_SC_OPEN_MAX));
9 exit(0);
10 }
Вот несколько примеров, в которых указываются имена файлов, относящиеся к различным файловым системам:
solaris % pipeconf / значения по умолчанию в Solaris 2.6
PIPE_BUF = 5120, OPEN_MAX = 64
solaris % pipeconf /home
PIPE_BUF = 5120, OPEN_MAX = 64
solaris % pipeconf /tmp
PIPE_BUF = 5120, OPEN_MAX = 64
alpha % pipeconf / значения по умолчанию в Digital Unix 4.0B
PIPE_BUF = 4096, OPEN_MAX = 4096
alpha % pipeconf /usr
PIPE_BUF = 4096, OPEN_MAX = 4096
Покажем теперь, как изменить значение OPEN_MAX в Solaris, используя интерпретатор KornShell:
solaris % ulimit –nS отображение максимального количества дескрипторов, мягкоео граничение
64
solaris % ulimit –Nh отображение максимального количества дескрипторов, жесткое ограничение
1024
solaris % ulimit –nS 512 установка мягкого ограничения в 512
solaris % pipeconf / проверка внесенных изменений
PIPE_BUF = 5120, OPEN_MAX = 512
ПРИМЕЧАНИЕ
Хотя значение PIPE_BUF для FIFO, в принципе, может меняться в зависимости от файловой системы, к которой относится файл, на самом деле это очень редкий случай.
В главе 2 [21] описаны функции fpathconf, pathconf и sysconf, которые предоставляют информацию о некоторых ограничениях ядра во время выполнения программы. Стандарт Posix.1 определяет 12 констант, начинающихся с _РС_, и 52, начинающихся с _SC_. Системы Digital Unix 4.0B и Solaris 2.6 расширяют последнее ограничение, определяя около 100 констант, значения которых могут быть получены в момент выполнения программы с помощью sysconf.
Команда getconf определяется стандартом Posix.2 и выводит значения большинства этих ограничений. Например:
alpha % getconf OPEN_MAX
4096
alpha % getconf PIPE_BUF /
4096
4.12. Резюме
Именованные и неименованные каналы представляют собой базовые строительные блоки для множества приложений. Программные каналы (неименованные) обычно используются в интерпретаторе команд, а также внутри программ — часто для передачи информации от дочернего процесса к родительскому. Можно исключить часть кода, относящегося к использованию каналов (piре, fork, close, exec и waitpid), используя функции popen и pclose, которые берут на себя все тонкости и запускают интерпретатор команд.
Каналы FIFO похожи на программные каналы, но создаются вызовом mkfifo и затем могут быть открыты с помощью функции open. При открытии FIFO следует быть аккуратным, поскольку процесс может быть заблокирован, а зависит это от множества условий (см. табл. 4.1).
Используя программные каналы и FIFO, мы создали несколько вариантов приложении типа клиент-сервер: один сервер с несколькими клиентами, последовательный и параллельный серверы. Последовательный сервер единовременно обрабатывает запрос только от одного клиента; такие серверы обычно уязвимы для атак типа «отказ в обслуживании». Параллельный сервер запускает отдельный процесс или поток для обработки запроса нового клиента.
Одним из свойств программных каналов и FIFO является то, что данные по ним передаются в виде потоков байтов, аналогично соединению TCP. Деление этого потока на самостоятельные записи целиком предоставляется приложению. Мы увидим в следующих двух главах, что очереди сообщений автоматически расставляют границы между записями, аналогично тому, как это делается в дейтаграммах UDP.
Упражнения
1. При переходе от рис. 4.3 к рис. 4.4: что могло бы произойти, если бы дочерний процесс не закрывал дескриптор (close(fd[1]))?
2. Описывая mkfifo в разделе 4.6, мы сказали, что для открытия существующего FIFO или создания нового, если его не существует, следует вызвать mkfifо, проверить, не возвращается ли ошибка EEXIST, и вызвать open, если это происходит. Что если изменить логику и вызвать сначала open, а затем mkfifо, если FIFO не существует?
3. Что происходит при вызове popen в листинге 4.5, если в интерпретаторе возникает ошибка?
4. Удалите вызов open для FIFO сервера в листинге 4.10 и проверьте, приведет ли это к завершению работы сервера после отключения последнего клиента.
5. К листингу 4.10: мы отметили, что при запуске сервера его работа блокируется при вызове первой функции open, пока FIFO не будет открыт на запись первым клиентом. Как можно обойти это таким образом, чтобы обе функции open завершали работу немедленно, а блокирование происходило при первом вызове readline?
6. Что произойдет с клиентом в листинге 4.11, если поменять порядок вызовов open?
7. Почему сигнал отправляется процессу, в котором канал FIFO открыт на запись, после отключения последнего читающего клиента, а не читающему клиенту после отключения последнего пишущего?
8. Напишите небольшую тестирующую программу для определения того, возвращает ли fstat количество байтов в FIFO в качестве поля st_size структуры stat.
9. Напишите небольшую тестирующую программу для определения того, что возвращает функция select при проверке возможности записи в дескриптор канала, у которого закрыт второй конец.
ГЛАВА 5
Очереди сообщений Posix
5.1. Введение
Очередь сообщений можно рассматривать как связный список сообщений. Программные потоки с соответствующими разрешениями могут помещать сообщения в очередь, а потоки с другими соответствующими разрешениями могут извлекать их оттуда. Каждое сообщение представляет собой запись (вспомните сравнение потоков и сообщений в разделе 4.10), и каждому сообщению его отправителем присваивается приоритет. Для записи сообщения в очередь не требуется наличия ожидающего его процесса. Это отличает очереди сообщений от программных каналов и FIFO, в которые нельзя произвести запись, пока не появится считывающий данные процесс.
Читать дальшеИнтервал:
Закладка: