Читать «UNIX: взаимодействие процессов» онлайн - страница 54

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

20   /* файл успешно открыт, передача данных */

21   while (Fgets(mesg.mesg_data, MAXMESGDATA, fp) != NULL) {

22    mesg.mesg_len = strlen(mesg.mesg_data);

23    Mesg_send(writefd, &mesg);

24   }

25   Fclose(fp);

26  }

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

28  mesg.mesg_len = 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, заключается в том, что в этой пpoгрaммe мы пользуемся библиотечной функцией fgets для считывания содержимого файла построчно и затем отправляем клиенту строку за строкой.

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

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

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

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

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

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

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

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

Значение OPEN_MAX можно узнать, вызвав функцию sysconf, как мы вскоре покажем. Обычно его можно изменить из интерпретатора команд с помощью команды ulimit (в Bourne shell и KornShell, как мы вскоре покажем) или с помощью команды limit (в С shell). Оно может быть изменено и самим процессом с помощью вызова функции setrlimit (подробно описана в разделе 7.11 [21]).

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