5.4.5. Каналы FIFO

We use cookies. Read the Privacy and Cookie Policy

5.4.5. Каналы FIFO

Файл FIFO (First-In, First-Out — первым пришел, первым обслужен) — это канал, у которого есть имя в файловой системе. Любой процесс может открыть и закрыть такой файл. Процессы, находящиеся на противоположных концах канала, не обязаны быть связанными друг с другом. FIFO-файлы называют именованными каналами.

FIFO-файл создается с помощью команды mkfifo. Путь к файлу указывается в командной строке, например:

% mkfifo /tmp/fifo

% ls -l /tmp/fifo

prw-rw-rw- 1 samuel users 0 Jan 16 14:04 /tmp/fifo

Первый символ в строке режима (p) указывает на то, что файл имеет тип FIFO (именованный канал). Теперь в одном терминальном окне можно осуществлять чтение из файла с помощью команды

% cat < /tmp/fifo

а в другом окне можно выполнять запись в файл:

% cat > /tmp/fifo

Попробуйте во втором окне ввести какой-то текст и нажать <Enter>. Введенный текст немедленно отобразится в первом окне. Канал закрывается нажатием клавиш <Ctrl+D> во втором окне. FIFO-файл удаляется с помощью следующей команды:

% rm /tmp/fifo

Создание FIFO-файла

FIFO-файл можно создать программным путем с помощью функции mkfifo(). Первым аргументом является путь к файлу. Второй аргумент задает права доступа к каналу со стороны его владельца, группы и остальных пользователей (об этом пойдет речь в разделе 10.3, "Права доступа к файлам"). Поскольку у канала есть читающая и записывающая стороны, права доступа должны учитывать оба случая. Если канал не может быть создан (например, файл с таким именем уже существует), функция mkfifo() возвращает -1. Для работы функции требуется подключить к программе файлы <sys/types.h> и <sys/stat.h>.

Доступ к FIFO-файлу

К FIFO-файлу можно обращаться как к обычному файлу. При организации межзадачного взаимодействия одна программа должна открыть файл для записи, а другая - для чтения. Над файлом можно выполнять как низкоуровневые (open(), write(), read(), close() и др.), так и высокоуровневые (fopen(), fprintf(), fscanf(), fclose() и др.) функции.

Например, на низком уровне запись блока данных в FIFO-файл осуществляется следующим образом:

int fd = open(fifo_path, O_WRONLY);

write(fd, data, data_length);

close(fd);

А так выполняется чтение строки из FIFO-файла на высоком уровне:

FILE* fifo = fopen(fifo_path, "r");

fscanf(fifo, "%s", buffer);

fclose(fifo);

У FIFO-файла одновременно может быть несколько читающих и записывающих программ. Входные потоки разбиваются на атомарные блоки, размер которых определяется константой PIPE_BUF (4 Кбайт в Linux). Если несколько программ параллельно друг другу осуществляют запись в файл, их блоки будут чередоваться. То же самое относится к программам. одновременно читающим данные из файла.

Отличия от именованных каналов в Windows

Каналы операционных систем семейства Win32 очень напоминают каналы Linux. Основное различие касается именованных каналов, которые в Win32 функционируют скорее как сокеты. Именованные каналы Win32 способны соединять по сети процессы, выполняющиеся на разных компьютерах. В Linux для этой цели используются именно сокеты. Кроме того, в Win32 допускается, чтобы несколько программ чтения или записи работали с именованным каналом, не перекрывая потоки друг друга, а сами каналы поддерживают двунаправленный обмен данными.[17]