Главная страница Взаимодействие нетривиальных процессов Листинг 4.8. Заголовочный файл fifo.h, используемый и клиентом, и сервером pipe/fifo.h 1 #include unpipc.h 2 #define FIFOl /tmp/fifo.l 3 #define FIF02 /tmp/fifo.2 Листинг 4.9. Функция main независимого клиента pipe/client main.c 1 #include fifo.h 2 void clientCint. int); 3 int 4 mainCint argc. char **argv) 6 int readfd. writefd: 7 writefd - OpenCFIFOl. 0 WRONLY. 0); 8 readfd - Open(FIF02. 0 RDONLY. 0): 9 client(readfd. writefd): 10 CloseCreadfd); 11 Close(writefd): 12 Unlink(FIFOl): 13 Unlink(FIF02): 14 exit(O); 15 } ПРИМЕЧАНИЕ - Для программных каналов и каналов FIFO ядро ведет подсчет числа открытых дескрипторов, относящихся к ним, поэтому безразлично, кто именно вызовет unlink - клиент или сервер. Хотя эта функция и удаляет файл из файловой системы, она не влияет на открытые в момент ее выполнения дескрипторы. Однако для других форм IPC, таких как очереди сообщений стандарта System V, счетчик отсутствует, и если сервер удалит очередь после записи в нее последнего сообщения, она может быть удалена еще до того, как клиент это сообщение считает. Для запуска клиента и сервера запустите сервер в фоновом режиме: % server fifo & а затем запустите клиент. Можно было сделать и по-другому: запускать только программу-клиент, которая запускала бы сервер с помощью fork и exec. Клиент мог бы передавать серверу имена FIFO в качестве аргументов командной строки в команде exec, вместо того чтобы обе программы считывали их из заголовка. Но в этом случае сервер являлся бы дочерним процессом и проще было бы обойтись программным каналом. 4.7. Некоторые свойства именованных и.неименованных каналов Некоторые свойства именованных и неименованных каналов, относящиеся к их открытию, а также чтению и записи данных, заслуживают более пристального внимания. Прежде всего можно сделать дескриптор неблокируемым двумя способами. 4.7. Некоторые свойства именованных и неименованных каналов 1. При вызове open указать флаг 0 NONBLOCK. Например, первый вызов open в листинге 4.9 мог бы выглядеть так: writefd - OpenCFIFOl. 0 WRONLY OJONBLOCK. 0): 2. Если дескриптор уже открыт, можно использовать fcntl для включения флага 0 NONBLOCK. Этот прием нужно применять для программных каналов, поскольку для них не вызывается функция open и нет возможности указать флаг 0 NONBLOCK при ее вызове. Используя fcntl, мы сначала получаем текущий статус файла с помощью F GETFL, затем добавляем к нему с помощью побитового логического сложения (OR) флаг 0 NONBLOCK и записываем новый статус с помощью команды F SETFL: int flags: if С Cflags - fcntlCfd. F GETFL. 0)) < 0) err sysC F GETFL error ): flags I- 0 NONBL0CK: if CfcntlCfd. F SETFL. flags) < 0) err sysC F SETFL error ); Будьте аккуратны с программами, которые просто устанавливают требуемый флаг, поскольку при этом сбрасываются все прочие флаги состояния: /* Неправильное отключение блокировки */ if CfcntlCfd. FJETFL. OJONBLOCK) < 0) err sysC F SETFL error ): Таблица 4.1 иллюстрирует действие флага, отключающего блокировку, при открытии очереди и при чтении данных из пустого программного канала или канала FIFO. Таблица 4.1. Действие флага 0 NONBLOCK на именованные и неименованные каналы Операция Наличие открытых каналов Блокировка включена (по умолчанию) Флаг O.NONBLOCK установлен Открытие (open) FIFO только для чтения Открытие (open) FIFO только для чтения Открытие (open) FIFO только для записи Открытие (open) FIFO только для записи Чтение (read) из пустого программного канала или FIFO FIFO открыт на запись FIFO не открыт на запись FIFO открыт на чтение FIFO не открыт на чтение Программный канал или FIFO открыт на запись Возвращается код успешного завершения операции Процесс блокируется, пока FIFO не будет открыт на запись Возвращает код успешного завершения операдаи Блокируется до тех пор, пока FIFO не будет открыт на чтение Блокируется до тех пор, пока в программный канал или FIFO не будут помещены данные или они не будут закрыты всеми процессами, которыми они бьши открыты на запись Возвращается код успешного заверше-шения операции Возвращается код успешного завершения операции Возвращает код успешного завершения операции Возвращает ошибку с кодом ENXIO Возвращает ошибку с кодом EAGAIN Таблица 4.1 (продолжение) Операция Наличие открытых каналов Блокировка включена (по умолчанию) Флаг 0 NONBLOCK установлен Чтение (read) из пустого программного канала или FIFO Запись (write) в программный канал или FIFO Запись (write) в программный канал или FIFO Программный канал или read возвращает О FIFO не открыт на (конец файла) запись Программный канал или (См. в тексте) FIFO открыт на чтение Программный канал или Программному потоку FIFO не открыт на посьшается сигнал чтение SIGPIPE read возвращает О (конец файла) (См. в тексте) Программному потоку посылается сигнал SIGPIPE Запомните несколько дополнительных правил, действующих при чтении и записи данных в программные каналы и FIFO. Ш При попытке считать больше данных, чем в данный момент содержится в программном канале или FIFO, возвращается только имеющийся объем данных. Нужно предусмотреть обработку ситуации, в которой функция read возвращает меньше данных, чем было запрошено. Ш Если количество байтов, направленных на запись функции write, не превышает значения PIPE BUF (ограничение, устанавливаемое стандартом Posix, о котором более подробно рассказывается в разделе 4.11), то ядро гарантирует атомарность операции записи. Это означает, что если два процесса запишут данные в программный канал или FIFO приблизительно одновременно, то в буфер будут помещены сначала все данные от первого процесса, а затем от второго, либо наоборот. Данные от двух процессов при этом не будут смешиваться. Однако если количество байтов превышает значение PIPE BUF, атомарность операции записи не гарантируется. ПРИМЕЧАНИЕ Posix.l требует, чтобы значение PIPE BUF равнялось по меньшей мере 512. Характерные значения, встречающиеся на практике, лежат в диапазоне от 1024 (BSD/OS 3.1) до 5120 байт (Solaris 2.6). В разделе 4.11 приведен текст программы, выводящей значение этой константы. Установка флага ONONBLOCK не влияет на атомарность операции записи в программный канал или FIFO - она определяется исключительно объемом посылаемых данных в сравнении с величиной PIPEBUF. Однако если для программного канала или FIFO отключена блокировка, возвращаемое функцией wri te значение зависит от количества байтов, отправленных на запись, и наличия свободного места в программном канале или FIFO. Если количество байтов не превышает величины PIPEBUF, то: □ Если в канале достаточно места для записи требуемого количества данных, они будут переданы все сразу. □ Если места в программном канале или FIFO недостаточно для записи требуемого объема данных, происходит немедленное завершение работы функ-
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |