Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [ 26 ] 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

24 }

25 Fclose(fp);

26 }

27 /* отправка сообщения нулевой длины для обозначения конца связи */

28 mesg.mesgjen - 0:

29 Mesg send(writefd. &mesg);

30 }

Считывание имени файла из канала IPC, открытие файла

8-18 Сервер принимает от клиента имя файла. Хотя значение mesg type, равное 1, нигде не используется (оно затирается функцией mesg recv из листинга 4.14), мы будем использовать ту же функцию при работе с очередями сообщений System V (листинг 6.8), а в данном случае в этом значении уже возникает потребность (см., например, листинг 6.11). Стандартная функция ввода-вывода fopen открывает файл, что отличается от листинга 4.3, где вызывалась функция open для получения дескриптора файла. Причина, по которой мы воспользовались fopen, заключается в том, что в этой программе мы пользуемся библиотечной функцией fgets для считывания содержимого файла построчно и затем отправляем клиенту строку за строкой.

Отправка файла клиенту

19-26 Если вызов fopen оказывается успешным, содержимое файла считывается с помощью функции fgets и затем отправляется клиенту построчно. Сообщение с нулевой длиной означает конец файла.

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

Функции main, вызывающие новые функции client и server, вообще не претерпели никаких изменений. Мы можем использовать либо версию для работы с каналами (листинг 4.1), либо версию для работы с FIFO (листинг 4.6).

4.11. Ограничения программных каналов и FIFO

На программные каналы и каналы FIFO системой накладываются всего два ограничения:

я OPEN MAX - максимальное количество дескрипторов, которые могут быть одновременно открыты некоторым процессом (Posix устанавливает для этой величины ограничение снизу - 16);

РI PE BUF - максимальное количество данных, для которого гарантируется атомарность операции записи (описано в разделе 4.7; Posix требует по меньшей мере 512 байт).

Значение OPEN MAX можно узнать, вызвав функцию sysconf, как мы вскоре покажем. Обычно его можно изменить из интерпретатора команд с помощью



команды u11m1t (в Bourne shell и KornShell, как мы вскоре покажем) или с помощью команды 11m1t (в С shell). Оно может быть изменено и самим процессом с помощью вызова функции setrl 1m1t (подробно описана в разделе 7.11 [21]).

Значение PIPE BUF обычно определено в заголовочном файле <11m1ts.h>, но с точки зрения стандарта Posix оно представляет собой переменную, зависимую от полного имени файла. Это означает, что ее значение может меняться в зависимости от указываемого имени файла (для FIFO, поскольку каналы имен не имеют), поскольку разные имена могут относиться к разным файловым системам и эти файловые системы могут иметь различные характеристики. Это значение можно получить в момент выполнения программы, вызвав либо pathconf, либо fpathconf. В листинге 4.17 приведен пример, выводящий текущее значение этих двух ограничений.

Листинг 4.17. Определение значений PIPE BUF и OPEN MAX во время выполнения

pipe/pipeconf,с

1 #include unpipc.h

2 int

3 HBinCint argc. char **argv)

5 if (argc != 2)

6 err quit( usage: pipeconf <pathname> );

7 printf( PIPE BUF - %d. OPEN MAX - %й\n.

8 Pathconf(argv[l]. PC PIPE BUF). Sysconf( SC OPEN MAX));

9 exit(O); 10 }

Вот несколько примеров, в которых указываются имена файлов, относящиеся к различным файловым системам:

Solaris % pipeconf / значения по умолчанию в Solaris 2.6

PIPE BUF - 5120. OPEN MAX - 64

Solaris % pipeconf /home

PIPEJUF = 5120. OPEN MAX = 64

Solaris % pipeconf /tmp

PIPE BUF = 5120. OPEN MAX - 64

alpha % pipeconf / значения no умолчанию в Digital Unix 4.OB

PIPEJUF - 4096. OPEN MAX - 4096

alpha % pipeconf /usr

PIPEJUF - 4096. OPEN MAX - 4096

Покажем теперь, как изменить значение OPEN MAX в Solaris, используя интерпретатор KornShell:

Solaris % ulimit -nS отображение максимального количества дескрипторов.

мягкое ограничение

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.0В и Solaris 2.6 расширяют последнее ограничение, определяя около 100 констант, значения которых могут быть получены в момент выполнения программы с помощью sysconf.

Команда getconf определяется стандартом Posix.2 и выводит значения большинства этих ограничений. Например;

alpha % getconf OPEN MAX

4096

alpha % getconf PIPE BUF /

4096

4.12. Резюме

Именованные и неименованные каналы представляют собой базовые строительные блоки для множества приложений. Программные каналы (неименованные) обычно используются в интерпретаторе команд, а также внутри программ - часто для передачи информации от дочернего процесса к родительскому. Можно исключить часть кода, относящегося к использованию каналов (р1 ре, fork, с1 ose, exec и wa1tp1d), используя функции рореп и pclose, которые берут на себя все тонкости и запускают интерпретатор команд.

Каналы FIFO похожи на программные каналы, но создаются вызовом mkfifo и затем могут быть открыты с помощью функции open. При открытии FIFO следует быть аккуратным, поскольку процесс может быть заблокирован, а зависит это от множества условий (см. табл. 4.1).

Используя программные каналы и FIFO, мы создали несколько вариантов приложений типа клиент-сервер: один сервер с несколькими клиентами, последовательный и параллельный серверы. Последовательный сервер единовременно обрабатывает запрос только от одного клиента; такие серверы обычно уязвимы для атак типа отказ в обслуживании . Параллельный сервер запускает отдельный процесс или поток для обработки запроса нового клиента.

Одним из свойств программных каналов и FIFO является то, что данные по ним передаются в виде потоков байтов, аналогично соединению TCP. Деление этого потока на самостоятельные записи целиком предоставляется приложению. Мы увидим в следующих двух главах, что очереди сообщений автоматически расставляют границы между записями, аналогично тому, как это делается в дейтаграммах UDP.

Упражнения

1. При переходе от рис. 4.3 к рис. 4.4: что могло бы произойти, если бы дочерний процесс не закрывал дескриптор (close(fd[l]))?



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [ 26 ] 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.