Для запуска клиента и сервера запустите сервер в фоновом режиме:
% server_fifo &
а затем запустите клиент. Можно было сделать и по-другому: запускать только программу-клиент, которая запускала бы сервер с помощью fork и exec. Клиент мог бы передавать серверу имена FIFO в качестве аргументов командной строки в команде exec, вместо того чтобы обе программы считывали их из заголовка. Но в этом случае сервер являлся бы дочерним процессом и проще было бы обойтись программным каналом.
4.7. Некоторые свойства именованных и неименованных каналов
Некоторые свойства именованных и неименованных каналов, относящиеся к их открытию, а также чтению и записи данных, заслуживают более пристального внимания. Прежде всего можно сделать дескриптор неблокируемым двумя способами.
1. При вызове open указать флаг O_NONBLOCK. Например, первый вызов open в листинге 4.9 мог бы выглядеть так:
writefd = Open(FIFO1, O_WRONLY | O_NONBLOCK, 0);
2. Если дескриптор уже открыт, можно использовать fcntl для включения флага O_NONBLOCK. Этот прием нужно применять для программных каналов, поскольку для них не вызывается функция open и нет возможности указать флаг O_NONBLOCK при ее вызове. Используя fcntl, мы сначала получаем текущий статус файла с помощью F_GETFL, затем добавляем к нему с помощью побитового логического сложения (OR) флаг O_NONBLOCK и записываем новый статус с помощью команды F_SETFL:
int flags;
if ((flags = fcntl(fd, F_GETFL, 0)) < 0) err_sys("F_GETFL error");
flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0) err_sys("F_SETFL error");
Будьте аккуратны с программами, которые просто устанавливают требуемый флаг, поскольку при этом сбрасываются все прочие флаги состояния:
/* Неправильное отключение блокировки */
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) err_sys("F_SETFL error");
Таблица 4.1 иллюстрирует действие флага, отключающего блокировку, при открытии очереди и при чтении данных из пустого программного канала или канала FIFO.
Таблица 4.1. Действие флага O_NONBLOCK на именованные и неименованные каналы
Операция |
Наличие открытых каналов |
Блокировка включена (по умолчанию) |
Флаг O_NONBLOCK установлен |
Открытие (open) FIFO только для чтения |
FIFO открыт на запись |
Возвращается код успешного завершения операции |
Возвращается код успешного завершения операции |
Открытие (open) FIFO только для чтения |
FIFO не открыт на запись |
Процесс блокируется, пока FIFO не будет открыт на запись |
Возвращается код успешного завершения операции |
Открытие (open) FIFO только для записи |
FIFO открыт на чтение |
Возвращает код успешного завершения операции |
Возвращает код успешного завершения операции |
Открытие (open) FIFO только для записи |
FIFO не открыт на чтение |
Блокируется до тех пор, пока FIFO не будет открыт на чтение |
Возвращает ошибку с кодом ENXIO |
Чтение (read) из пустого программного канала или FIFO |
Программный канал или FIFO открыт на запись |
Блокируется до тех пор, пока в программный канал или FIFO не будут помещены данные или они не будут закрыты всеми процессами, которыми они были открыты на запись |
Возвращает ошибку с кодом EAGAIN |
Чтение (read) из пустого программного канала или FIFO |
Программный канал или FIFO не открыт на запись |
read возвращает 0 (конец файла) |
read возвращает 0 (конец файла) |
Запись (write) в программный канал или FIFO |
Программный канал или FIFO открыт на чтение |
(См. в тексте) |
(См. в тексте) |
Запись (write) в программный канал или FIFO |
Программный канал или FIFO не открыт на чтение |
Программному потоку посылается сигнал SIGPIPE |
Программному потоку посылается сигнал SIGPIPE |
Запомните несколько дополнительных правил, действующих при чтении и записи данных в программные каналы и FIFO.
■ При попытке считать больше данных, чем в данный момент содержится в программном канале или FIFO, возвращается только имеющийся объем данных. Нужно предусмотреть обработку ситуации, в которой функция read возвращает меньше данных, чем было запрошено.
■ Если количество байтов, направленных на запись функции write, не превышает значения PIPE_BUF (ограничение, устанавливаемое стандартом Posix, о котором более подробно рассказывается в разделе 4.11), то ядро гарантирует атомарность операции записи. Это означает, что если два процесса запишут данные в программный канал или FIFO приблизительно одновременно, то в буфер будут помещены сначала все данные от первого процесса, а затем от второго, либо наоборот. Данные от двух процессов при этом не будут смешиваться. Однако если количество байтов превышает значение PIPEBUF, атомарность операции записи не гарантируется.
Читать дальше
Конец ознакомительного отрывка
Купить книгу