Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

Никогда не уничтожайте FIFO, т.к. у вас нет способа узнать, не использует ли FIFO другая программа.

O_RDONLY и O_WRONLY без O_NONBLOCK

Теперь у вас есть тестовая программа, и вы можете проверить комбинации пар. Обратите внимание на то, что первая программа, считыватель, помещена в фоновый режим.

$ ./fifo2 O_RDONLY &

[1] 152

Process 152 opening FIFO

$ ./fifo2 O_WRONLY

Process 153 opening FIFO

Process 152 result 3

Process 153 result 3

Process 152 finished

Process 153 finished

Это,

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

Примечание

Когда процесс в ОС Linux заблокирован, он не потребляет ресурсы ЦП, поэтому этот метод синхронизации очень эффективен с точки зрения использования ЦП.

O_RDONLY с O_NONBLOCK и O_WRONLY

В следующем примере читающий процесс выполняет вызов

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

$ ./fifо2 O_RDONLY O_NONBLOCK &

[1] 160

Process 160 opening fifo

$ ./fifo2 O_WRONLY

Process 161 opening FIFO

Process 160 result 3

Process 161 result 3

Process 160 finished

Process 161 finished

[1]+ Done ./fifo2 O_RDONLY O_NONBLOCK

Эти два примера — вероятно, самые распространенные комбинации режимов

open
. Не стесняйтесь использовать программу-пример для экспериментов с другими возможными комбинациями.

Чтение из каналов FIFO и запись в них

Применение режима

O_NONBLOCK
влияет на поведение вызовов
read
и
write
в каналах FIFO.

Вызов

read
, применяемый для чтения из пустого блокирующего FIFO (открытого без флага
O_NONBLOCK
), будет ждать до тех пор, пока не появятся данные, которые можно прочесть. Вызов
read
, применяемый в неблокирующем FIFO, напротив, при отсутствии данных вернет 0 байтов.

Вызов

write
для записи в полностью блокирующий канал FIFO будет ждать до тех пор, пока данные не смогут быть записаны. Вызов
write
, применяемый к FIFO,
который не может принять все байты, предназначенные для записи, либо:

 будет аварийно завершен, если был запрос на запись

PIPE_BUF
байтов или меньше и данные не могут быть записаны;

 запишет часть данных, если был запрос на запись более чем

PIPE_BUF
байтов, и вернет количество реально записанных байтов, которое может быть и 0.

Размер FIFO — очень важная характеристика. Существует накладываемый системой предел объема данных, которые могут быть в FIFO в любой момент времени. Он задается директивой

#define PIPE_BUF
, обычно находящейся в файле limits.h. В ОС Linux и многих других UNIX-подобных системах он обычно равен 4096 байт, но в некоторых системах может быть и 512 байт. Система гарантирует, что операции записи PIPE_BUF или меньшего количества байтов в канал FIFO, который был открыт
O_WRONLY
(т.е. блокирующий), запишут или все байты, или ни одного.

Несмотря на то, что этот предел не слишком важен в простом случае с одним записывающим каналом FIFO и одним читающим FIFO, очень распространено использование одного канала FIFO, позволяющего разным программам отправлять запросы к этому единственному каналу FIFO. Если несколько разных программ попытаются писать в FIFO в одно и то же время, жизненно важно, чтобы блоки данных из разных программ не перемежались друг с другом, т. е. каждая операция write должна быть "атомарной". Как это сделать?

Если вы ручаетесь, что все ваши запросы

write
адресованы блокирующему каналу FIFO и их размер меньше
PIPE_BUF
байтов, система гарантирует, что данные никогда не будут разделены. Вообще это неплохая идея — ограничить объем данных, передаваемых через FIFO блоком в
PIPE_BUF
байтов, если вы не используете единственный пишущий и единственный читающий процессы.

Выполните упражнение 13.12.

Упражнение 13.12. Связь процессов с помощью каналов FIFO

Для того чтобы увидеть, как несвязанные процессы могут общаться с помощью именованных каналов, вам понадобятся две отдельные программы fifo3.c и fifo4.c.

1. Первая программа — поставщик. Она создает канал, если требуется, и затем записывает в него данные как можно быстрее.

Примечание

Поскольку пример иллюстративный, нас не интересуют конкретные данные, и мы не беспокоимся об инициализации буфера, В обоих листингах затененные строки содержат изменения, внесенные в программу fifo2.c помимо удаления кода со всеми аргументами командной строки.

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <limits.h>

#include <sys/types.h>

#include <sys/stat.h>

#define FIFO_NAME "/tmp/my_fifo"

#define BUFFER_SIZE PIPE_BUF

Поделиться с друзьями: